home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / JTable.java < prev    next >
Text File  |  1998-06-30  |  137KB  |  3,742 lines

  1. /*
  2.  * @(#)JTable.java    1.82 98/04/13
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20.  
  21. package com.sun.java.swing;
  22.  
  23. import java.lang.Thread;
  24.  
  25. import java.util.*;
  26.  
  27. import java.awt.*;
  28. import java.awt.event.*;
  29.  
  30. import java.io.Serializable;
  31. import java.io.ObjectOutputStream;
  32. import java.io.ObjectInputStream;
  33. import java.io.IOException;
  34.  
  35. import java.beans.PropertyChangeListener;
  36.  
  37. import com.sun.java.accessibility.*;
  38.  
  39. import com.sun.java.swing.*;
  40. import com.sun.java.swing.event.*;
  41. import com.sun.java.swing.plaf.*;
  42. import com.sun.java.swing.table.*;
  43. import com.sun.java.swing.border.*;
  44.  
  45. /**
  46.  *  JTable is a user-interface component that presents data in a two-dimensional
  47.  *  table format. The JTable has many features that make it possible to
  48.  *  customize its rendering and editing but provides defaults
  49.  *  for these features so that simple tables can be set up easily.
  50.  *  For example, to set up a table with 10 rows and 10 columns of numbers:
  51.  *  <p>
  52.  *  <pre>
  53.  *       TableModel dataModel = new AbstractTableModel() {
  54.  *           public int getColumnCount() { return 10; }
  55.  *           public int getRowCount() { return 10;}
  56.  *           public Object getValueAt(int row, int col) { return new Integer(row*col); }
  57.  *       };
  58.  *       JTable table = new JTable(dataModel);
  59.  *       JScrollPane scrollpane = new JScrollPane(table);
  60.  *  </pre>
  61.  *  <p>
  62.  *  Because the JTable is now much easier to set up with custom models
  63.  *  the DefaultTableModel is less useful than it was in previous releases.
  64.  *  Instead of copying the data in an application into the DefaultTableModel,
  65.  *  we recommend wrapping it in the methods of the TableModel interface and
  66.  *  passing the real data to the JTable as above. This technique is nearly as concise
  67.  *  as using a DefaultTableModel and starting this way has a number of advantages
  68.  *  over the longer term. In particular: it is a scalable technique,
  69.  *  is easier to handle dynamic or editable tables and often results in much
  70.  *  more efficient applications because the model is free to choose the
  71.  *  internal representation that best suits the data.
  72.  *  <p>
  73.  *  The "Table" directory in the examples/demo area gives a number of complete
  74.  *  examples of JTable usage, covering how the JTable can be used to provide
  75.  *  an editable view of data taken from a database and how to modify the columns
  76.  *  in the display to use specialized renderers and editors.
  77.  *  <p>
  78.  *  The JTable uses integers exclusively to refer to both the rows and the columns
  79.  *  of the model that it displays. The JTable simply takes a tabular range of cells
  80.  *  and uses <code>getValueAt(int, int)</code> to retrieve and display the values
  81.  *  from the model.
  82.  *  <p>
  83.  *  If <code>getTableHeader().setReorderingAllowed(boolean)</code> is used to
  84.  *  enable column reordering columns may be rearranged in the JTable so that the
  85.  *  view's columns appear in a different order to the columns in the model.
  86.  *  This does not affect the implementation of the model at all: when the
  87.  *  columns are reordered, the JTable maintains the new order of the columns
  88.  *  internally and converts its column indices before querying the model.
  89.  *  So, when writing a TableModel, it is not necessary to listen for column
  90.  *  reordering events as the the model will be queried in its own co-ordinate
  91.  *  system regardless of what is happening in the view.
  92.  *  In the examples area there is a demonstration of a sorting algorithm making
  93.  *  use of exactly this technique to interpose yet another co-ordinate system
  94.  *  where the order of the rows is changed, rather than the order of the columns.
  95.  *  <p>
  96.  *  The general rule for the JTable API and the APIs of all its associated classes,
  97.  *  including the the column model and both the row and column selection models, is:
  98.  *  methods using integer indices for rows and columns always use the co-ordinate
  99.  *  system of the view. There are three exceptions to this rule:
  100.  *  <ul>
  101.  *  <li> All references to rows and columns in the TableModel
  102.  *       interface are in the co-ordinate system of the model.
  103.  *  <li> The index <I>modelIndex</I> in the TableColumn constructors
  104.  *       refers to the index of the column in the model, not the view.
  105.  *  <li> All constructors for the TableModelEvent, which describes changes
  106.  *       that have taken place in a table model, use the co-ordinate system
  107.  *       of the model.
  108.  *  </ul>
  109.  *  The TableColumn provides a slot for holding an identifier or "tag" for each column
  110.  *  and the JTable and TableColumModel both support <I>getColumn(Object id)</I>
  111.  *  conveniences for locating columns by their identifier. If no identifier is
  112.  *  explicitly set, the TableColumn returns its header value (the name of the column)
  113.  *  as a default. A different identifier, which can be of any type, can be set
  114.  *  using the TableColumn's <I>setIdentifier()</I> method. All of the JTable's
  115.  *  functions operate correctly regardless of the type and uniqueness of these
  116.  *  identifiers.
  117.  *  <p>
  118.  *  The <I>convertColumnIndexToView()</I> and
  119.  *  <I>convertColumnIndexToModel()</I> methods have been provided to
  120.  *  convert between the two co-ordinate systems but
  121.  *  they are rarely needed during normal use.
  122.  * <p>
  123.  * See <a href="http://java.sun.com/docs/books/tutorial/ui/swing/table.html">How to Use Tables</a>
  124.  * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
  125.  * for further documentation.
  126.  * <p>
  127.  * For the keyboard keys used by this component in the standard Look and
  128.  * Feel (L&F) renditions, see the
  129.  * <a href="doc-files/Key-Index.html#JTable">JTable</a> key assignments.
  130.  * <p>
  131.  * Warning: serialized objects of this class will not be compatible with
  132.  * future swing releases.  The current serialization support is appropriate
  133.  * for short term storage or RMI between Swing1.0 applications.  It will
  134.  * not be possible to load serialized Swing1.0 objects with future releases
  135.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  136.  * baseline for the serialized form of Swing objects.
  137.  *
  138.  *
  139.  * @beaninfo
  140.  *   attribute: isContainer false
  141.  *
  142.  * @version 1.82 04/13/98
  143.  * @author Philip Milne
  144.  * @author Alan Chung
  145.  */
  146. public class JTable extends JComponent implements TableModelListener, Scrollable,
  147.     TableColumnModelListener, ListSelectionListener, CellEditorListener,
  148.     Accessible
  149. {
  150. //
  151. // Static Constants
  152. //
  153.  
  154.     /** Do not auto resize column when table is resized. */
  155.     public static final int     AUTO_RESIZE_OFF = 0;
  156.  
  157.     /** Auto resize last column only when table is resized */
  158.     public static final int     AUTO_RESIZE_LAST_COLUMN = 1;
  159.  
  160.     /** Proportionately resize all columns when table is resized */
  161.     public static final int     AUTO_RESIZE_ALL_COLUMNS = 2;
  162.  
  163.  
  164. //
  165. // Instance Variables
  166. //
  167.  
  168.     /** The TableModel of the table */
  169.     protected TableModel        dataModel;
  170.  
  171.     /** The TableColumnModel of the table */
  172.     protected TableColumnModel  columnModel;
  173.  
  174.     /** The ListSelectionModel of the table, used to keep track of row selections */
  175.     protected ListSelectionModel selectionModel;
  176.  
  177.     /** The TableHeader working with the table */
  178.     protected JTableHeader      tableHeader;
  179.  
  180.     /** The height of all rows in the table */
  181.     protected int               rowHeight;
  182.  
  183.     /** The height margin between rows */
  184.     protected int               rowMargin;
  185.  
  186.     /** The color of the grid */
  187.     protected Color             gridColor;
  188.  
  189.     /** The table draws horizontal lines between cells if showHorizontalLines is true */
  190.     protected boolean           showHorizontalLines;
  191.  
  192.     /** The table draws vertical lines between cells if showVerticalLines is true */
  193.     protected boolean           showVerticalLines;
  194.  
  195.     /**
  196.      *  This mode value determines if table automatically resizes the
  197.      *  width the table's columns to take up the entire width of the
  198.      *  table, and how it does the resizing.
  199.      */
  200.     protected int               autoResizeMode;
  201.  
  202.     /**
  203.      *  The table will query the TableModel to build the default
  204.      *  set of columns if this is true.
  205.      */
  206.     protected boolean           autoCreateColumnsFromModel;
  207.  
  208.     /** Used by the Scrollable interface to determine the initial visible area */
  209.     protected Dimension         preferredViewportSize;
  210.  
  211.     /** Row selection allowed in this table */
  212.     protected boolean           rowSelectionAllowed;
  213.  
  214.     /**
  215.      * If this is true, then both a row selection and a column selection
  216.      * can be non-empty at the same time, the selected cells are the
  217.      * the cells whose row and column are both selected.
  218.      */
  219.     protected boolean           cellSelectionEnabled;
  220.  
  221.     /** If editing, Component that is handling the editing. */
  222.     transient protected Component       editorComp;
  223.  
  224.     /**
  225.      * The object that overwrites the screen real estate occupied by the
  226.      * current cell and allows the user to change those contents.
  227.      */
  228.     transient protected TableCellEditor cellEditor;
  229.  
  230.     /** Identifies the column of the cell being edited. */
  231.     transient protected int             editingColumn;
  232.  
  233.     /** Identifies the row of the cell being edited. */
  234.     transient protected int             editingRow;
  235.  
  236.     /**
  237.      * A table of objects that display the contents of a cell,
  238.      * indexed by class.
  239.      */
  240.     transient protected Hashtable defaultRenderersByColumnClass;
  241.  
  242.     /**
  243.      * A table of objects that display and edit the contents of a cell,
  244.      * indexed by class.
  245.      */
  246.     transient protected Hashtable defaultEditorsByColumnClass;
  247.  
  248.     /** The foreground color of selected cells */
  249.     protected Color selectionForeground;
  250.  
  251.     /** The background color of selected cells */
  252.     protected Color selectionBackground;
  253.  
  254. //
  255. // Constructors
  256. //
  257.  
  258.     /**
  259.      * Constructs a default JTable which is initialized with a default
  260.      * data model, a default column model, and a default selection
  261.      * model.
  262.      *
  263.      * @see #createDefaultDataModel()
  264.      * @see #createDefaultColumnModel()
  265.      * @see #createDefaultSelectionModel()
  266.      */
  267.     public JTable() {
  268.         this(null, null, null);
  269.     }
  270.  
  271.     /**
  272.      * Constructs a JTable which is initialized with <i>dm</i> as the
  273.      * data model, a default column model, and a default selection
  274.      * model.
  275.      *
  276.      * @param dm        The data model for the table
  277.      * @see #createDefaultColumnModel()
  278.      * @see #createDefaultSelectionModel()
  279.      */
  280.     public JTable(TableModel dm) {
  281.         this(dm, null, null);
  282.     }
  283.  
  284.     /**
  285.      * Constructs a JTable which is initialized with <i>dm</i> as the
  286.      * data model, <i>cm</i> as the column model, and a default selection
  287.      * model.
  288.      *
  289.      * @param dm        The data model for the table
  290.      * @param cm        The column model for the table
  291.      * @see #createDefaultSelectionModel()
  292.      */
  293.     public JTable(TableModel dm, TableColumnModel cm) {
  294.         this(dm, cm, null);
  295.     }
  296.  
  297.     /**
  298.      * Constructs a JTable which is initialized with <i>dm</i> as the
  299.      * data model, <i>cm</i> as the column model, and <i>sm</i> as the
  300.      * selection model.  If any of the parameters are <b>null</b> this
  301.      * method will initialize the table with the corresponding
  302.      * default model. The <i>autoCreateColumnsFromModel</i> flag is set
  303.      * to false if <i>cm</i> is non-null, otherwise it is set to true
  304.      * and the column model is populated with suitable TableColumns
  305.      * for the columns in <i>dm</i>.
  306.      *
  307.      * @param dm        The data model for the table
  308.      * @param cm        The column model for the table
  309.      * @param sm        The row selection model for the table
  310.      * @see #createDefaultDataModel()
  311.      * @see #createDefaultColumnModel()
  312.      * @see #createDefaultSelectionModel()
  313.      */
  314.     public JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
  315.         super();
  316.         setLayout(null);
  317.  
  318.         if (cm == null) {
  319.             cm = createDefaultColumnModel();
  320.             autoCreateColumnsFromModel = true;
  321.         }
  322.         setColumnModel(cm);
  323.  
  324.         if (sm == null)
  325.             sm = createDefaultSelectionModel();
  326.         setSelectionModel(sm);
  327.  
  328.     // Set the model last, that way if the autoCreatColumnsFromModel has
  329.     // been set above, we will automatically populate an empty columnModel
  330.     // with suitable columns for the new model.
  331.         if (dm == null)
  332.             dm = createDefaultDataModel();
  333.         setModel(dm);
  334.  
  335.         initializeLocalVars();
  336.         updateUI();
  337.     }
  338.  
  339.     /**
  340.      * Constructs a JTable with <i>numRows</i> and <i>numColumns</i> of
  341.      * empty cells using the DefaultTableModel.  The columns will have
  342.      * names of the form "A", "B", "C", etc.
  343.      *
  344.      * @param numRows           The number of rows the table holds
  345.      * @param numColumns        The number of columns the table holds
  346.      * @see com.sun.java.swing.table.DefaultTableModel
  347.      */
  348.     public JTable(int numRows, int numColumns) {
  349.         this(new DefaultTableModel(numRows, numColumns));
  350.     }
  351.  
  352.     /**
  353.      * Constructs a JTable to display the values in the Vector of Vectors,
  354.      * <i>rowData</i>, with column names, <i>columnNames</i>.
  355.      * The Vectors contained in <i>rowData</i> should contain the values
  356.      * for that row. In other words, the value of the cell at row 1,
  357.      * column 5 can be obtained with the following code:
  358.      * <p>
  359.      * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
  360.      * <p>
  361.      * All rows must be of the same length as <i>columnNames</i>.
  362.      * <p>
  363.      * @param rowData           The data for the new table
  364.      * @param columnNames       Names of each column
  365.      */
  366.     public JTable(final Vector rowData, final Vector columnNames) {
  367.         this(new AbstractTableModel() {
  368.             public String getColumnName(int column) { return columnNames.elementAt(column).toString(); }
  369.             public int getRowCount() { return rowData.size(); }
  370.             public int getColumnCount() { return columnNames.size(); }
  371.             public Object getValueAt(int row, int column) {
  372.                 return ((Vector)rowData.elementAt(row)).elementAt(column);
  373.             }
  374.             public boolean isCellEditable(int row, int column) { return true; }
  375.             public void setValueAt(Object value, int row, int column) {
  376.                 ((Vector)rowData.elementAt(row)).setElementAt(value, column);
  377.             }
  378.         });
  379.     }
  380.  
  381.     /**
  382.      * Constructs a JTable to display the values in the two dimensional array,
  383.      * <i>rowData</i>, with column names, <i>columnNames</i>.
  384.      * <i>rowData</i> is an Array of rows, so the value of the cell at row 1,
  385.      * column 5 can be obtained with the following code:
  386.      * <p>
  387.      * <pre> rowData[1][5]; </pre>
  388.      * <p>
  389.      * All rows must be of the same length as <i>columnNames</i>.
  390.      * <p>
  391.      * @param rowData           The data for the new table
  392.      * @param columnNames       Names of each column
  393.      */
  394.     public JTable(final Object[][] rowData, final Object[] columnNames) {
  395.         this(new AbstractTableModel() {
  396.             public String getColumnName(int column) { return columnNames[column].toString(); }
  397.             public int getRowCount() { return rowData.length; }
  398.             public int getColumnCount() { return columnNames.length; }
  399.             public Object getValueAt(int row, int col) { return rowData[row][col]; }
  400.             public boolean isCellEditable(int row, int column) { return true; }
  401.             public void setValueAt(Object value, int row, int col) {
  402.                 rowData[row][col] = value;
  403.             }
  404.         });
  405.     }
  406.  
  407.     /**
  408.      * Calls <code>configureEnclosingScrollPane</code>.
  409.      *
  410.      * @see #configureEnclosingScrollPane
  411.      */
  412.     public void addNotify() {
  413.         super.addNotify();
  414.         configureEnclosingScrollPane();
  415.     }
  416.  
  417.     /**
  418.      * If the JTable is the viewportView of an enclosing JScrollPane
  419.      * (the usual situation), configure this ScrollPane by, amongst other things,
  420.      * installing the table's tableHeader as the columnHeaderView of the scrollpane.
  421.      * When a JTable is added to a JScrollPane in the usual way,
  422.      * using <code>new JScrollPane(myTable)</code>, <code>addNotify</code> is
  423.      * called in the JTable (when the table is added to the viewport).
  424.      * JTable's <code>addNotify</code> method in turn calls this method
  425.      * which is protected so that this default installation procedure can
  426.      * be overridden by a subclass.
  427.      *
  428.      * @see #addNotify
  429.      */
  430.     protected void configureEnclosingScrollPane() {
  431.         Container p = getParent();
  432.         if (p instanceof JViewport) {
  433.             Container gp = p.getParent();
  434.             if (gp instanceof JScrollPane) {
  435.                 JScrollPane scrollPane = (JScrollPane)gp;
  436.                 // Make certain we are the viewPort's view and not, for
  437.                 // example, the rowHeaderView of the scrollPane -
  438.                 // an implementor of fixed columns might do this.
  439.                 JViewport viewport = scrollPane.getViewport();
  440.                 if (viewport == null || viewport.getView() != this) {
  441.                     return;
  442.                 }
  443.                 scrollPane.setColumnHeaderView(getTableHeader());
  444.                 scrollPane.getViewport().setBackingStoreEnabled(true);
  445.                 scrollPane.setBorder(UIManager.getBorder("Table.scrollPaneBorder"));
  446.             }
  447.         }
  448.     }
  449.  
  450. //
  451. // Static Methods
  452. //
  453.  
  454.     /**
  455.      * Equivalent to <code>new JScrollPane(aTable)</code>.
  456.      *
  457.      * @deprecated As of Swing version 1.0.2,
  458.      * replaced by <code>new JScrollPane(aTable)</code>.
  459.      */
  460.     static public JScrollPane createScrollPaneForTable(JTable aTable) {
  461.         return new JScrollPane(aTable);
  462.     }
  463.  
  464. //
  465. // Table Attributes
  466. //
  467.  
  468.     /**
  469.      * Sets the tableHeader working with this JTable to <I>newHeader</I>.
  470.      * It is legal to have a <B>null</B> tableHeader.
  471.      *
  472.      * @param   newHeader                       new tableHeader
  473.      * @see     #getTableHeader()
  474.      * @beaninfo
  475.      * description: The JTableHeader instance which renders the column headers.
  476.      */
  477.     public void setTableHeader(JTableHeader newHeader) {
  478.         if (tableHeader != newHeader) {
  479.             // Release the old header
  480.             if (tableHeader != null)
  481.                 tableHeader.setTable(null);
  482.  
  483.             tableHeader = newHeader;
  484.             if (tableHeader != null)
  485.                 tableHeader.setTable(this);
  486.         }
  487.     }
  488.  
  489.     /**
  490.      * Returns the tableHeader working with this JTable.
  491.      *
  492.      * @return  the tableHeader working with the receiver
  493.      * @see     #setTableHeader()
  494.      */
  495.     public JTableHeader getTableHeader() {
  496.         return tableHeader;
  497.     }
  498.  
  499.     /**
  500.      * Sets the height for rows to <I>newRowHeight</I> and invokes tile
  501.      *
  502.      * @param   newRowHeight                    new row height
  503.      * @exception IllegalArgumentException      If <I>newRowHeight</I> is
  504.      *                                          less than 1.
  505.      * @see     #getRowHeight()
  506.      * @beaninfo
  507.      * description: The height of the cells including the inter-cell spacing.
  508.      */
  509.     public void setRowHeight(int newHeight) {
  510.         if (newHeight <= 0) {
  511.             throw new IllegalArgumentException("New row height less than 1");
  512.         }
  513.         rowHeight = newHeight;
  514.  
  515.         resizeAndRepaint();
  516.     }
  517.  
  518.     /**
  519.      * Returns the height of a table row in the receiver.
  520.      * The default row height is 16.0.
  521.      *
  522.      * @return  the height of each row in the receiver
  523.      * @see     #setRowHeight()
  524.      */
  525.     public int getRowHeight() {
  526.         return rowHeight;
  527.     }
  528.  
  529.     /**
  530.      * Sets the width and height between cells to <I>newSpacing</I> and
  531.      * redisplays the receiver.
  532.      *
  533.      * @param   newSpacing              The new width and height intercellSpacing
  534.      * @see     #getIntercellSpacing()
  535.      * @beaninfo
  536.      * description: The spacing between the cells, drawn in the background color of the JTable.
  537.      */
  538.     public void setIntercellSpacing(Dimension newSpacing) {
  539.         // Set the rowMargin here and columnMargin in the TableColumnModel
  540.         rowMargin = newSpacing.height;
  541.         getColumnModel().setColumnMargin(newSpacing.width);
  542.  
  543.         resizeAndRepaint();
  544.     }
  545.  
  546.     /**
  547.      * Returns the horizontal and vertical spacing between cells.
  548.      * The default spacing is (3, 2).
  549.      *
  550.      * @return  the horizontal and vertical spacing between cells
  551.      * @see     #setIntercellSpacing()
  552.      */
  553.     public Dimension getIntercellSpacing() {
  554.         return new Dimension(getColumnModel().getColumnMargin(), rowMargin);
  555.     }
  556.  
  557.     /**
  558.      * Sets the color used to draw grid lines to <I>color</I> and redisplays
  559.      * the receiver.
  560.      * The default color is gray.
  561.      *
  562.      * @param   color                           new color of the grid
  563.      * @exception IllegalArgumentException      if <I>color</I> is null
  564.      * @see     #getGridColor()
  565.      */
  566.     public void setGridColor(Color newColor) {
  567.         if (newColor == null) {
  568.             throw new IllegalArgumentException("New color is null");
  569.         }
  570.         gridColor = newColor;
  571.  
  572.         // Redraw
  573.         repaint();
  574.     }
  575.  
  576.     /**
  577.      * Returns the color used to draw grid lines. The default color is gray.
  578.      *
  579.      * @return  the color used to draw grid lines
  580.      * @see     #setGridColor()
  581.      */
  582.     public Color getGridColor() {
  583.         return gridColor;
  584.     }
  585.  
  586.     /**
  587.      *  Sets whether the receiver draws grid lines around cells.
  588.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  589.      *  There is no getShowGrid() method as the this state is held
  590.      *  in two variables: showHorizontalLines and showVerticalLines
  591.      *  each of which may be queried independently.
  592.      *
  593.      * @param   flag                    true if table view should draw grid lines
  594.      *
  595.      * @see     #setShowVerticalLines
  596.      * @see     #setShowHorizontalLines
  597.      * @beaninfo
  598.      * description: The color used to draw the grid lines.
  599.      */
  600.     public void setShowGrid(boolean b) {
  601.         setShowHorizontalLines(b);
  602.         setShowVerticalLines(b);
  603.  
  604.         // Redraw
  605.         repaint();
  606.     }
  607.  
  608.     /**
  609.      *  Sets whether the receiver draws horizontal lines between cells.
  610.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  611.      *
  612.      * @param   flag                    true if table view should draw horizontal lines
  613.      * @see     #getShowHorizontalLines
  614.      * @see     #setShowGrid
  615.      * @see     #setShowVerticalLines
  616.      * @beaninfo
  617.      * description: Whether horizontal lines should be drawn in between the cells.
  618.      */
  619.     public void setShowHorizontalLines(boolean b) {
  620.         showHorizontalLines = b;
  621.  
  622.         // Redraw
  623.         repaint();
  624.     }
  625.  
  626.     /**
  627.      *  Sets whether the receiver draws vertical lines between cells.
  628.      *  If <I>flag</I> is true it does; if it is false it doesn't.
  629.      *
  630.      * @param   flag                    true if table view should draw vertical lines
  631.      * @see     #getShowVerticalLines
  632.      * @see     #setShowGrid
  633.      * @see     #setShowHorizontalLines
  634.      * @beaninfo
  635.      * description: Whether vertical lines should be drawn in between the cells.
  636.      */
  637.     public void setShowVerticalLines(boolean b) {
  638.         showVerticalLines = b;
  639.  
  640.         // Redraw
  641.         repaint();
  642.     }
  643.  
  644.     /**
  645.      * Returns true if the receiver draws horizontal lines between cells, false if it
  646.      * doesn't. The default is true.
  647.      *
  648.      * @return  true if the receiver draws horizontal lines between cells, false if it
  649.      *          doesn't
  650.      * @see     #setShowHorizontalLines
  651.      */
  652.     public boolean getShowHorizontalLines() {
  653.         return showHorizontalLines;
  654.     }
  655.  
  656.     /**
  657.      * Returns true if the receiver draws vertical lines between cells, false if it
  658.      * doesn't. The default is true.
  659.      *
  660.      * @return  true if the receiver draws vertical lines between cells, false if it
  661.      *          doesn't
  662.      * @see     #setShowVerticalLines
  663.      */
  664.     public boolean getShowVerticalLines() {
  665.         return showVerticalLines;
  666.     }
  667.  
  668.     /**
  669.      * Sets the table's auto resize mode when the table is resized.
  670.      *
  671.      * @param   mode            One of 3 legal values: AUTO_RESIZE_OFF,
  672.      *                          AUTO_RESIZE_LAST_COLUMN, AUTO_RESIZE_ALL_COLUMNS
  673.      *
  674.      * @see     #getAutoResizeMode()
  675.      * @see     #sizeColumnsToFit()
  676.      * @beaninfo
  677.      * description: Whether the columns should adjust themselves automatically to accomodate changes.
  678.      *        enum: AUTO_RESIZE_OFF          JTable.AUTO_RESIZE_OFF
  679.      *              AUTO_RESIZE_LAST_COLUMN  JTable.AUTO_RESIZE_LAST_COLUMN
  680.      *              AUTO_RESIZE_ALL_COLUMNS  JTable.AUTO_RESIZE_ALL_COLUMNS
  681.      */
  682.     public void setAutoResizeMode(int mode) {
  683.         if ((mode == AUTO_RESIZE_ALL_COLUMNS) ||
  684.             (mode == AUTO_RESIZE_LAST_COLUMN) ||
  685.             (mode == AUTO_RESIZE_OFF)) {
  686.             autoResizeMode = mode;
  687.             resizeAndRepaint();
  688.             tableHeader.resizeAndRepaint();
  689.         }
  690.     }
  691.  
  692.     /**
  693.      * Returns auto resize mode of the table.  The default is
  694.      * AUTO_RESIZE_ALL_COLUMNS.
  695.      *
  696.      * @return  the autoResizeMode of the table
  697.      *
  698.      * @see     #setAutoResizeMode()
  699.      * @see     #sizeColumnsToFit()
  700.      */
  701.     public int getAutoResizeMode() {
  702.         return autoResizeMode;
  703.     }
  704.  
  705.     /**
  706.      * Sets the table's autoCreateColumnsFromModel flag.  This method
  707.      * will call createDefaultColumnsFromModel() if <i>createColumns</i>
  708.      * is true.
  709.      *
  710.      * @param   createColumns   true if JTable should auto create columns
  711.      * @see     #getAutoCreateColumnsFromModel()
  712.      * @see     #createDefaultColumnsFromModel()
  713.      * @beaninfo
  714.      * description: Automatically populate the columnModel when a new TableModel is submitted.
  715.      */
  716.     public void setAutoCreateColumnsFromModel(boolean createColumns) {
  717.         if (autoCreateColumnsFromModel != createColumns) {
  718.             autoCreateColumnsFromModel = createColumns;
  719.  
  720.             if (autoCreateColumnsFromModel)
  721.                 createDefaultColumnsFromModel();
  722.         }
  723.     }
  724.  
  725.     /**
  726.      * Returns whether the table will create default columns from the model.
  727.      * If this is true, setModel() will clear any existing columns and
  728.      * create new columns from the new model.  Also if the event in the
  729.      * the tableChanged() notification specified the entired table changed
  730.      * then the columns will be rebuilt.  The default is true.
  731.      *
  732.      * @return  the autoCreateColumnsFromModel of the table
  733.      * @see     #setAutoCreateColumnsFromModel()
  734.      * @see     #createDefaultColumnsFromModel()
  735.      */
  736.     public boolean getAutoCreateColumnsFromModel() {
  737.         return autoCreateColumnsFromModel;
  738.     }
  739.  
  740.     /**
  741.      * This method will create default columns for the table from
  742.      * the data model using the getColumnCount() and getColumnType() methods
  743.      * defined in the TableModel interface.
  744.      * <p>
  745.      * This method will clear any exsiting columns before creating the
  746.      * new columns based on information from the model.
  747.      *
  748.      * @see     #getAutoCreateColumnsFromModel()
  749.      */
  750.     public void createDefaultColumnsFromModel() {
  751.         TableModel m = getModel();
  752.         if (m != null) {
  753.             // Remove any current columns
  754.             TableColumnModel cm = getColumnModel();
  755.             cm.removeColumnModelListener(this);
  756.             while (cm.getColumnCount() > 0)
  757.                 cm.removeColumn(cm.getColumn(0));
  758.  
  759.             // Create new columns from the data model info
  760.             for (int i = 0; i < m.getColumnCount(); i++) {
  761.                 TableColumn newColumn = new TableColumn(i);
  762.                 addColumn(newColumn);
  763.             }
  764.             cm.addColumnModelListener(this);
  765.         }
  766.     }
  767.  
  768.     /**
  769.      * Set a default renderer to be used if no renderer has been set in
  770.      * a TableColumn.
  771.      *
  772.      * @see     #getDefaultRenderer
  773.      * @see     #setDefaultEditor
  774.      */
  775.     public void setDefaultRenderer(Class columnClass, TableCellRenderer renderer) {
  776.         defaultRenderersByColumnClass.put(columnClass, renderer);
  777.     }
  778.  
  779.     /**
  780.      * Returns the renderer to be used when no renderer has been set in
  781.      * a TableColumn. During the rendering of cells the renderer is fetched from
  782.      * a Hashtable of entries according to the class of the cells in the column. If
  783.      * there is no entry for this <I>columnClass</I> the method returns
  784.      * the entry for the most specific superclass. The JTable installs entries
  785.      * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  786.      * or replaced.
  787.      *
  788.      * @see     #setDefaultRenderer
  789.      * @see     #getColumnClass
  790.      */
  791.     public TableCellRenderer getDefaultRenderer(Class columnClass) {
  792.         if (columnClass == null) {
  793.             return null;
  794.         }
  795.         else {
  796.             Object renderer = defaultRenderersByColumnClass.get(columnClass);
  797.             if (renderer != null) {
  798.                 return (TableCellRenderer)renderer;
  799.             }
  800.             else {
  801.                 return getDefaultRenderer(columnClass.getSuperclass());
  802.             }
  803.         }
  804.     }
  805.  
  806.     /**
  807.      * Set a default editor to be used if no editor has been set in
  808.      * a TableColumn. If no editing is required in a table or a
  809.      * particular column in a table use the isCellEditable()
  810.      * method in the TableModel interface to ensure that the
  811.      * JTable will not start an editor in these columns.
  812.      *
  813.      * @see     TableModel#isCellEditable
  814.      * @see     #getDefaultEditor
  815.      * @see     #setDefaultRenderer
  816.      */
  817.     public void setDefaultEditor(Class columnClass, TableCellEditor editor) {
  818.         defaultEditorsByColumnClass.put(columnClass, editor);
  819.     }
  820.  
  821.     /**
  822.      * Returns the editor to be used when no editor has been set in
  823.      * a TableColumn. During the editing of cells the editor is fetched from
  824.      * a Hashtable of entries according to the class of the cells in the column. If
  825.      * there is no entry for this <I>columnClass</I> the method returns
  826.      * the entry for the most specific superclass. The JTable installs entries
  827.      * for <I>Object</I>, <I>Number</I> and <I>Boolean</I> all which can be modified
  828.      * or replaced.
  829.      *
  830.      * @see     #setDefaultEditor
  831.      * @see     #getColumnClass
  832.      */
  833.     public TableCellEditor getDefaultEditor(Class columnClass) {
  834.         if (columnClass == null) {
  835.             return null;
  836.         }
  837.         else {
  838.             Object editor = defaultEditorsByColumnClass.get(columnClass);
  839.             if (editor != null) {
  840.                 return (TableCellEditor)editor;
  841.             }
  842.             else {
  843.                 return getDefaultEditor(columnClass.getSuperclass());
  844.             }
  845.         }
  846.     }
  847.  
  848. //
  849. // Selection methods
  850. //
  851.     /**
  852.      * Sets the table's selection mode to allow only single selections, a single
  853.      * contiguous interval, or multiple intervals.
  854.      *
  855.      * NOTE:<br>
  856.      * JTable provides all the methods for handling column and row selection.
  857.      * When setting states, such as setSelectionMode, it not only
  858.      * updates the mode for the row selection model but also sets similar
  859.      * values in the selection model of the columnModel.
  860.      * If you want to have states that is different between rows and columns
  861.      * you can get the columnModel and change that directly.
  862.      * <p>
  863.      * Both the row and column selection models for the JTable default
  864.      * to using a DefaultListSelectionModel so that JTable works the same
  865.      * way as the JList. See setSelectionMode() in JList for details
  866.      * about the modes.
  867.      *
  868.      * @see JList#setSelectionMode
  869.      * @beaninfo
  870.      * description: The selection mode used by the row and column selection models.
  871.      *        enum: SINGLE_SELECTION            ListSelectionModel.SINGLE_SELECTION
  872.      *              SINGLE_INTERVAL_SELECTION   ListSelectionModel.SINGLE_INTERVAL_SELECTION
  873.      *              MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
  874.      */
  875.     public void setSelectionMode(int selectionMode) {
  876.         clearSelection();
  877.         getSelectionModel().setSelectionMode(selectionMode);
  878.         getColumnModel().getSelectionModel().setSelectionMode(selectionMode);
  879.     }
  880.  
  881.     /**
  882.      * Sets whether the rows in this model can be selected.
  883.      *
  884.      * @see #getRowSelectionAllowed()
  885.      * @beaninfo
  886.      * description: If true, an entire row is selected for each selected cell.
  887.      */
  888.     public void setRowSelectionAllowed(boolean flag) {
  889.         clearSelection();
  890.         rowSelectionAllowed = flag;
  891.     }
  892.  
  893.     /**
  894.      * Returns true if rows can be selected.
  895.      *
  896.      * @return true if rows can be selected
  897.      * @see #setRowSelectionAllowed()
  898.      */
  899.     public boolean getRowSelectionAllowed() {
  900.         return rowSelectionAllowed;
  901.     }
  902.  
  903.     /**
  904.      * Sets whether the columns in this model can be selected.
  905.      *
  906.      * @see #getColumnSelectionAllowed()
  907.      * @beaninfo
  908.      * description: If true, an entire column is selected for each selected cell.
  909.      */
  910.     public void setColumnSelectionAllowed(boolean flag) {
  911.         clearSelection();
  912.         columnModel.setColumnSelectionAllowed(flag);
  913.     }
  914.  
  915.     /**
  916.      * Returns true if columns can be selected.
  917.      *
  918.      * @return true if columns can be selected.
  919.      * @see #setColumnSelectionAllowed
  920.      */
  921.     public boolean getColumnSelectionAllowed() {
  922.         return columnModel.getColumnSelectionAllowed();
  923.     }
  924.  
  925.     /**
  926.      * Sets whether this table allows both a column selection and a
  927.      * row selection to exist at the same time. When set, this results
  928.      * in a facility to select a rectangular region of cells in the display.
  929.      * This flag over-rides the row and column selection
  930.      * modes ensuring that cell selection is possible whenever this flag is set.
  931.  
  932.      * @see #getCellSelectionEnabled
  933.      * @beaninfo
  934.      * description: Select a rectangular region of cells rather than rows or columns.
  935.      */
  936.     public void setCellSelectionEnabled(boolean flag) {
  937.         clearSelection();
  938.         cellSelectionEnabled = flag;
  939.     }
  940.  
  941.     /**
  942.      * Returns true if simultaneous row and column selections are allowed
  943.      *
  944.      * @return true if simultaneous row and column selections are allowed
  945.      * @see #setCellSelectionEnabled
  946.      */
  947.     public boolean getCellSelectionEnabled() {
  948.         return cellSelectionEnabled;
  949.     }
  950.  
  951.     /**
  952.      *  If a column is selected, then this selects all columns.  Similarly,
  953.      *  if a row is selected, then, this selects all rows.  If both a column
  954.      *  and a row are selected at the time this method is invoked, then
  955.      *  all columns and rows are selected.
  956.      */
  957.     public void selectAll() {
  958.         if (getSelectedRowCount() > 0) {
  959.             // select all rows
  960.             int count = getRowCount();
  961.             if (count > 0)
  962.                 setRowSelectionInterval(0, count);
  963.         }
  964.  
  965.         if (getSelectedColumnCount() > 0) {
  966.             int count = getColumnCount();
  967.             if (count > 0)
  968.                 setColumnSelectionInterval(0, count);
  969.         }
  970.     }
  971.  
  972.     /**
  973.      * Deselects all selected columns and rows.  If empty selection is not
  974.      * allowed, then it leaves the first row selected.
  975.      */
  976.     public void clearSelection() {
  977.         columnModel.getSelectionModel().clearSelection();
  978.         selectionModel.clearSelection();
  979.     }
  980.  
  981.     /**
  982.      * Selects the rows from <i>index0</i> to <i>index1</i> inclusive.
  983.      *
  984.      * @param   index0 one end of the interval.
  985.      * @param   index1 other end of the interval
  986.      */
  987.     public void setRowSelectionInterval(int index0, int index1) {
  988.         selectionModel.setSelectionInterval(index0, index1);
  989.     }
  990.  
  991.     /**
  992.      * Selects the columns from <i>index0</i> to <i>index1</i> inclusive.
  993.      *
  994.      * @param   index0 one end of the interval.
  995.      * @param   index1 other end of the interval
  996.      */
  997.     public void setColumnSelectionInterval(int index0, int index1) {
  998.         columnModel.getSelectionModel().setSelectionInterval(index0, index1);
  999.     }
  1000.  
  1001.     /**
  1002.      * Adds the rows from <i>index0</i> to <i>index0</i> inclusive to
  1003.      * the current selection.
  1004.      *
  1005.      * @param   index0 one end of the interval.
  1006.      * @param   index1 other end of the interval
  1007.      */
  1008.     public void addRowSelectionInterval(int index0, int index1) {
  1009.         selectionModel.addSelectionInterval(index0, index1);
  1010.     }
  1011.  
  1012.     /**
  1013.      * Adds the columns from <i>index0</i> to <i>index0</i> inclusive to
  1014.      * the current selection.
  1015.      *
  1016.      * @param   index0 one end of the interval.
  1017.      * @param   index1 other end of the interval
  1018.      */
  1019.     public void addColumnSelectionInterval(int index0, int index1) {
  1020.         columnModel.getSelectionModel().addSelectionInterval(index0, index1);
  1021.     }
  1022.  
  1023.     /**
  1024.      * Deselects the rows from <i>index0</i> to <i>index0</i> inclusive.
  1025.      *
  1026.      * @param   index0 one end of the interval.
  1027.      * @param   index1 other end of the interval
  1028.      */
  1029.     public void removeRowSelectionInterval(int index0, int index1) {
  1030.         selectionModel.removeSelectionInterval(index0, index1);
  1031.     }
  1032.  
  1033.     /**
  1034.      * Deselects the columns from <i>index0</i> to <i>index0</i> inclusive.
  1035.      *
  1036.      * @param   index0 one end of the interval.
  1037.      * @param   index1 other end of the interval
  1038.      */
  1039.     public void removeColumnSelectionInterval(int index0, int index1) {
  1040.         columnModel.getSelectionModel().removeSelectionInterval(index0, index1);
  1041.     }
  1042.  
  1043.     /**
  1044.      * Returns the index of the last row selected or added to the selection.
  1045.      *
  1046.      * @return the index of the last row selected or added to the selection,
  1047.      *         (lead selection) or -1 if no row is selected.
  1048.      * @see #getSelectedRows()
  1049.      */
  1050.     public int getSelectedRow() {
  1051.         if (selectionModel != null) {
  1052.             return selectionModel.getAnchorSelectionIndex();
  1053.         }
  1054.         return -1;
  1055.     }
  1056.  
  1057.     /**
  1058.      * Returns the index of the last column selected or added to the selection.
  1059.      *
  1060.      * @return the index of the last column selected or added to the selection,
  1061.      *         (lead selection) or -1 if no column is selected.
  1062.      * @see #getSelectedColumns()
  1063.      */
  1064.     public int getSelectedColumn() {
  1065.         return columnModel.getSelectionModel().getAnchorSelectionIndex();
  1066.     }
  1067.  
  1068.     /**
  1069.      * Returns the indices of all selected rows.
  1070.      *
  1071.      * @return an array of ints containing the indices of all selected rows,
  1072.      *         or an empty array if no row is selected.
  1073.      * @see #getSelectedRow()
  1074.      */
  1075.     public int[] getSelectedRows() {
  1076.         if (selectionModel != null) {
  1077.             int iMin = selectionModel.getMinSelectionIndex();
  1078.             int iMax = selectionModel.getMaxSelectionIndex();
  1079.  
  1080.             if ((iMin == -1) || (iMax == -1)) {
  1081.                 return new int[0];
  1082.             }
  1083.  
  1084.             int[] rvTmp = new int[1+ (iMax - iMin)];
  1085.             int n = 0;
  1086.             for(int i = iMin; i <= iMax; i++) {
  1087.                 if (selectionModel.isSelectedIndex(i)) {
  1088.                     rvTmp[n++] = i;
  1089.                 }
  1090.             }
  1091.             int[] rv = new int[n];
  1092.             System.arraycopy(rvTmp, 0, rv, 0, n);
  1093.             return rv;
  1094.         }
  1095.         return  new int[0];
  1096.     }
  1097.  
  1098.     /**
  1099.      * Returns the indices of all selected columns.
  1100.      *
  1101.      * @return an array of ints containing the indices of all selected columns,
  1102.      *         or an empty array if no column is selected.
  1103.      * @see #getSelectedColumn()
  1104.      */
  1105.     public int[] getSelectedColumns() {
  1106.         return columnModel.getSelectedColumns();
  1107.     }
  1108.  
  1109.     /**
  1110.      * Returns the number of selected rows.
  1111.      *
  1112.      * @return the number of selected rows, 0 if no columns are selected
  1113.      */
  1114.     public int getSelectedRowCount() {
  1115.         if (selectionModel != null) {
  1116.             int iMin = selectionModel.getMinSelectionIndex();
  1117.             int iMax = selectionModel.getMaxSelectionIndex();
  1118.             int count = 0;
  1119.  
  1120.             for(int i = iMin; i <= iMax; i++) {
  1121.                 if (selectionModel.isSelectedIndex(i)) {
  1122.                     count++;
  1123.                 }
  1124.             }
  1125.             return count;
  1126.         }
  1127.         return 0;
  1128.     }
  1129.  
  1130.     /**
  1131.      * Returns the number of selected columns.
  1132.      *
  1133.      * @return the number of selected columns, 0 if no columns are selected
  1134.      */
  1135.     public int getSelectedColumnCount() {
  1136.         return columnModel.getSelectedColumnCount();
  1137.     }
  1138.  
  1139.     /**
  1140.      * Returns true if the row at the specified index is selected
  1141.      *
  1142.      * @return true if the row at index <I>row</I> is selected, where 0 is the
  1143.      *              first row
  1144.      * @exception IllegalArgumentException      if <I>row</I> is not in the
  1145.      *                                          valid range
  1146.      */
  1147.     public boolean isRowSelected(int row) {
  1148.         if (selectionModel != null)
  1149.             return selectionModel.isSelectedIndex(row);
  1150.         return false;
  1151.     }
  1152.  
  1153.     /**
  1154.      * Returns true if the column at the specified index is selected
  1155.      *
  1156.      * @return true if the column at index <I>column</I> is selected, where
  1157.      *              0 is the first column
  1158.      * @exception IllegalArgumentException      if <I>column</I> is not in the
  1159.      *                                          valid range
  1160.      */
  1161.     public boolean isColumnSelected(int column) {
  1162.         return columnModel.getSelectionModel().isSelectedIndex(column);
  1163.     }
  1164.  
  1165.     /**
  1166.      * Returns true if the cell at the specified position is selected.
  1167.      *
  1168.      * @return true if the cell at index <I>(row, column)</I> is selected,
  1169.      *              where the first row and first column are at index 0
  1170.      * @exception IllegalArgumentException      if <I>row</I> or <I>column</I>
  1171.      *                                          are not in the valid range
  1172.      */
  1173.     public boolean isCellSelected(int row, int column) {
  1174.         if (cellSelectionEnabled)
  1175.             return isRowSelected(row) && isColumnSelected(column);
  1176.         else
  1177.             return (getRowSelectionAllowed() && isRowSelected(row)) ||
  1178.                    (getColumnSelectionAllowed() && isColumnSelected(column));
  1179.     }
  1180.  
  1181.     /**
  1182.      * Returns the foreground color for selected cells.
  1183.      *
  1184.      * @return the Color object for the foreground property
  1185.      * @see #setSelectionForeground
  1186.      * @see #setSelectionBackground
  1187.      */
  1188.     public Color getSelectionForeground() {
  1189.         return selectionForeground;
  1190.     }
  1191.  
  1192.     /**
  1193.      * Set the foreground color for selected cells.  Cell renderers
  1194.      * can use this color to render text and graphics for selected
  1195.      * cells.
  1196.      * <p>
  1197.      * The default value of this property is defined by the look
  1198.      * and feel implementation.
  1199.      * <p>
  1200.      * This is a JavaBeans bound property.
  1201.      *
  1202.      * @param selectionForeground  the Color to use in the foreground
  1203.      *                             for selected list items
  1204.      * @see #getSelectionForeground
  1205.      * @see #setSelectionBackground
  1206.      * @see #setForeground
  1207.      * @see #setBackground
  1208.      * @see #setFont
  1209.      * @beaninfo
  1210.      *       bound: true
  1211.      * description: A default foreground color for selected cells.
  1212.      */
  1213.     public void setSelectionForeground(Color selectionForeground) {
  1214.         Color oldValue = this.selectionForeground;
  1215.         this.selectionForeground = selectionForeground;
  1216.         firePropertyChange("selectionForeground", oldValue, selectionForeground);
  1217.     }
  1218.  
  1219.     /**
  1220.      * Returns the background color for selected cells.
  1221.      *
  1222.      * @return the Color used for the background of selected list items
  1223.      * @see #setSelectionBackground
  1224.      * @see #setSelectionForeground
  1225.      */
  1226.     public Color getSelectionBackground() {
  1227.         return selectionBackground;
  1228.     }
  1229.  
  1230.     /**
  1231.      * Set the background color for selected cells.  Cell renderers
  1232.      * can use this color to the fill selected cells.
  1233.      * <p>
  1234.      * The default value of this property is defined by the look
  1235.      * and feel implementation.
  1236.      * <p>
  1237.      * This is a JavaBeans bound property.
  1238.      *
  1239.      * @param selectionBackground  the Color to use for the background
  1240.      *                             of selected cells
  1241.      * @see #getSelectionBackground
  1242.      * @see #setSelectionForeground
  1243.      * @see #setForeground
  1244.      * @see #setBackground
  1245.      * @see #setFont
  1246.      * @beaninfo
  1247.      *       bound: true
  1248.      * description: A default background color for selected cells.
  1249.      */
  1250.     public void setSelectionBackground(Color selectionBackground) {
  1251.         Color oldValue = this.selectionBackground;
  1252.         this.selectionBackground = selectionBackground;
  1253.         firePropertyChange("selectionBackground", oldValue, selectionBackground);
  1254.     }
  1255.  
  1256.     /**
  1257.      * Returns the <B>TableColumn</B> object for the column in the table
  1258.      * whose identifier is equal to <I>identifier</I>, when compared using
  1259.      * <I>equals()</I>.
  1260.      *
  1261.      * @return  the TableColumn object with matching identifier
  1262.      * @exception IllegalArgumentException      if <I>identifier</I> is null or no TableColumn has this identifier
  1263.      *
  1264.      * @param   identifier                      the identifier object
  1265.      */
  1266.     public TableColumn getColumn(Object identifier) {
  1267.         TableColumnModel cm = getColumnModel();
  1268.         int columnIndex = cm.getColumnIndex(identifier);
  1269.         return cm.getColumn(columnIndex);
  1270.     }
  1271.  
  1272. //
  1273. // Informally implement the TableModel interface.
  1274. //
  1275.  
  1276.     /**
  1277.      * Return the index of the column in the model whose data is being displayed in
  1278.      * the column <I>viewColumnIndex</I> in the display. Returns <I>viewColumnIndex</I>
  1279.      * unchanged when <I>viewColumnIndex</I> is less than zero.
  1280.      *
  1281.      * @see #convertColumnIndexToView
  1282.      */
  1283.     public int convertColumnIndexToModel(int viewColumnIndex) {
  1284.         if (viewColumnIndex < 0) {
  1285.             return viewColumnIndex;
  1286.         }
  1287.         return getColumnModel().getColumn(viewColumnIndex).getModelIndex();
  1288.     }
  1289.  
  1290.     /**
  1291.      * Return the index of the column in the view which is displaying the
  1292.      * data from the column <I>modelColumnIndex</I> in the model. Returns
  1293.      * -1 if this column is not being displayed. Returns <I>modelColumnIndex</I>
  1294.      * unchanged when <I>modelColumnIndex</I> is less than zero.
  1295.      *
  1296.      * @see #convertColumnIndexToModel
  1297.      */
  1298.     public int convertColumnIndexToView(int modelColumnIndex) {
  1299.         if (modelColumnIndex < 0) {
  1300.             return modelColumnIndex;
  1301.         }
  1302.         TableColumnModel cm = getColumnModel();
  1303.         for (int column = 0; column < getColumnCount(); column++) {
  1304.             if (cm.getColumn(column).getModelIndex() == modelColumnIndex) {
  1305.                 return column;
  1306.             }
  1307.         }
  1308.         return -1;
  1309.     }
  1310.  
  1311.     /**
  1312.      * Returns the number of rows in the table.
  1313.      *
  1314.      * @see #getColumnCount()
  1315.      */
  1316.     public int getRowCount() {
  1317.         return getModel().getRowCount();
  1318.     }
  1319.  
  1320.     /**
  1321.      * Returns the number of columns in the column model, note this may
  1322.      * be different to the number of columns in the table model.
  1323.      *
  1324.      * @return  the number of columns in the table
  1325.      * @see #getRowCount()
  1326.      */
  1327.     public int getColumnCount() {
  1328.         return getColumnModel().getColumnCount();
  1329.     }
  1330.  
  1331.     /**
  1332.      * Returns the name of the column at the specified view position.
  1333.      *
  1334.      * @return the name of the column at position <I>column</I> in the view
  1335.      *         where the first column is column 0.
  1336.      */
  1337.     public String getColumnName(int column) {
  1338.         return getModel().getColumnName(convertColumnIndexToModel(column));
  1339.     }
  1340.  
  1341.     /**
  1342.      * Returns the type of the column at the specified view position.
  1343.      *
  1344.      * @return the type of the column at position <I>column</I> in the view
  1345.      *         where the first column is column 0.
  1346.      */
  1347.     public Class getColumnClass(int column) {
  1348.         return getModel().getColumnClass(convertColumnIndexToModel(column));
  1349.     }
  1350.  
  1351.     /**
  1352.      * Returns the cell value at <I>row</I> and <I>column</I>.
  1353.      * <p>
  1354.      * <b>NOTE</b>: The column is specified in the table view's display
  1355.      *              order, and not in the TableModel's column order.  This is
  1356.      *              an important distinction because as the user rearranges
  1357.      *              the columns in the table, what is at column 2 changes.
  1358.      *              Meanwhile the user's actions never affect the model's
  1359.      *              column ordering.
  1360.      *
  1361.      * @param   row             the row whose value is to be looked up
  1362.      * @param   column          the column whose value is to be looked up
  1363.      * @return  the Object at the specified cell
  1364.      */
  1365.     public Object getValueAt(int row, int column) {
  1366.         return getModel().getValueAt(row, convertColumnIndexToModel(column));
  1367.     }
  1368.  
  1369.     /**
  1370.      * Sets the value for the cell at <I>row</I> and <I>column</I>.
  1371.      * <I>aValue</I> is the new value.
  1372.      *
  1373.      * @param   aValue          the new value
  1374.      * @param   row             the row whose value is to be changed
  1375.      * @param   column          the column whose value is to be changed
  1376.      * @see #getValueAt()
  1377.      */
  1378.     public void setValueAt(Object aValue, int row, int column) {
  1379.         getModel().setValueAt(aValue, row, convertColumnIndexToModel(column));
  1380.     }
  1381.  
  1382.     /**
  1383.      * Returns true if the cell at <I>row</I> and <I>column</I>
  1384.      * is editable.  Otherwise, setValueAt() on the cell will not change
  1385.      * the value of that cell.
  1386.      *
  1387.      * @param   row      the row whose value is to be looked up
  1388.      * @param   column   the column whose value is to be looked up
  1389.      * @return  true if the cell is editable.
  1390.      * @see #setValueAt()
  1391.      */
  1392.     public boolean isCellEditable(int row, int column) {
  1393.         return getModel().isCellEditable(row, convertColumnIndexToModel(column));
  1394.     }
  1395. //
  1396. // Adding and removing columns in the view
  1397. //
  1398.  
  1399.     /**
  1400.      *  Appends <I>aColumn</I> to the end of the array of columns held by
  1401.      *  the JTable's column model.
  1402.      *  If the header value of <I>aColumn</I> is <I>null</I>,
  1403.      *  sets the header value of <I>aColumn</I> to the name
  1404.      *  returned by <code>getModel().getColumnName()</code>.
  1405.      *  <p>
  1406.      *  To add a column to the JTable to display the <I>modelColumn</I>'th column of
  1407.      *  data in the model, with a given <I>width</I>,
  1408.      *  <I>cellRenderer</I> and <I>cellEditor</I> you can use:
  1409.      *  <pre>
  1410.      *
  1411.      *      addColumn(new TableColumn(modelColumn, width, cellRenderer, cellEditor));
  1412.      *
  1413.      *  </pre>
  1414.      *  [All of the other constructors in the TableColumn can be used in place of
  1415.      *  this one.] The model column is stored inside the TableColumn and is used during
  1416.      *  rendering and editing to locate the appropriate data values in the
  1417.      *  model. The model column does not change when columns are reordered
  1418.      *  in the view.
  1419.      *
  1420.      *  @param  aColumn         The <B>TableColumn</B> to be added
  1421.      *  @see    #removeColumn
  1422.      */
  1423.     public void addColumn(TableColumn aColumn) {
  1424.         int modelColumn = aColumn.getModelIndex();
  1425.         String columnName = getModel().getColumnName(modelColumn);
  1426.         if (aColumn.getHeaderValue() == null) {
  1427.             aColumn.setHeaderValue(columnName);
  1428.         }
  1429.         getColumnModel().addColumn(aColumn);
  1430.     }
  1431.  
  1432.     /**
  1433.      *  Removes <I>aColumn</I> from the JTable's array of columns.
  1434.      *  Note: this method does not remove the column of data from the
  1435.      *  model it just removes the TableColumn that was displaying it.
  1436.      *
  1437.      *  @param  aColumn         The <B>TableColumn</B> to be removed
  1438.      *  @see    #addColumn
  1439.      */
  1440.     public void removeColumn(TableColumn aColumn) {
  1441.         getColumnModel().removeColumn(aColumn);
  1442.     }
  1443.  
  1444.     /**
  1445.      * Moves the column <I>column</I> to the position currently occupied by the
  1446.      * column <I>targetColumn</I>.  The old column at <I>targetColumn</I> is
  1447.      * shifted left or right to make room.
  1448.      *
  1449.      * @param   column                  the index of column to be moved
  1450.      * @param   targetColumn            the new index of the column
  1451.      */
  1452.     public void moveColumn(int column, int targetColumn) {
  1453.         getColumnModel().moveColumn(column, targetColumn);
  1454.     }
  1455.  
  1456. //
  1457. // Cover methods for various models and helper methods
  1458. //
  1459.  
  1460.     /**
  1461.      * Returns the index of the column that <I>point</I> lies in, or -1 if it
  1462.      * lies outside the receiver's bounds.
  1463.      *
  1464.      * @return  the index of the column that <I>point</I> lies in, or -1 if it
  1465.      *          lies outside the receiver's bounds
  1466.      * @see     #rowAtPoint
  1467.      */
  1468.     public int columnAtPoint(Point point) {
  1469.         return getColumnModel().getColumnIndexAtX(point.x);
  1470.     }
  1471.  
  1472.     /**
  1473.      * Returns the index of the row that <I>point</I> lies in, or -1 if is
  1474.      * not in the range [0, getRowCount()-1].
  1475.      *
  1476.      * @return  the index of the row that <I>point</I> lies in, or -1 if it
  1477.      *          is not in the range [0, getRowCount()-1]
  1478.      * @see     #columnAtPoint()
  1479.      */
  1480.     public int rowAtPoint(Point point) {
  1481.         int y = point.y;
  1482.  
  1483.  //       if (y < 0 || y >= getBounds().height) {
  1484.  //           return -1;
  1485.  //       }
  1486.  
  1487.         int rowHeight = getRowHeight();
  1488.         int rowSpacing = getIntercellSpacing().height;
  1489.         int totalRowHeight = rowHeight + rowSpacing;
  1490.         int result = y/totalRowHeight;
  1491.         if (result < 0) {
  1492.             return -1;
  1493.         }
  1494.         else if (result >= getRowCount()) {
  1495.             return -1;
  1496.         }
  1497.         else {
  1498.             return result;
  1499.         }
  1500.     }
  1501.  
  1502.     /**
  1503.      * Returns a rectangle locating the cell that lies at the intersection of
  1504.      * <I>row</I> and <I>column</I>.   If <I>includeSpacing</I> is true then
  1505.      * the value returned includes the intercellSpacing margin.  If it is false,
  1506.      * then the returned rect is inset by half of intercellSpacing.
  1507.      * (This is the true frame of the cell)
  1508.      *
  1509.      * @param   row                             the row to compute
  1510.      * @param   column                          the column to compute
  1511.      * @param   includeSpacing                  if true, the rect returned will
  1512.      *                                          include the correct
  1513.      *                                          intercellSpacing
  1514.      * @return  the rectangle containing the cell at index
  1515.      *          <I>row</I>,<I>column</I>
  1516.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1517.      *                                          are not in the valid range.
  1518.      */
  1519.     public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
  1520.         int index = 0;
  1521.         Rectangle cellFrame;
  1522.         int columnMargin = getColumnModel().getColumnMargin();
  1523.         Enumeration enumeration = getColumnModel().getColumns();
  1524.         TableColumn aColumn;
  1525.  
  1526.         cellFrame = new Rectangle();
  1527.         cellFrame.height = getRowHeight() + rowMargin;
  1528.         cellFrame.y = row * cellFrame.height;
  1529.  
  1530.         while (enumeration.hasMoreElements()) {
  1531.             aColumn = (TableColumn)enumeration.nextElement();
  1532.             cellFrame.width = aColumn.getWidth() + columnMargin;
  1533.  
  1534.             if (index == column)
  1535.                 break;
  1536.  
  1537.             cellFrame.x += cellFrame.width;
  1538.             index++;
  1539.         }
  1540.  
  1541.         if (!includeSpacing) {
  1542.             Dimension spacing = getIntercellSpacing();
  1543.             // This is not the same as grow(), it rounds differently.
  1544.             cellFrame.setBounds(cellFrame.x +      spacing.width/2,
  1545.                                 cellFrame.y +      spacing.height/2,
  1546.                                 cellFrame.width -  spacing.width,
  1547.                                 cellFrame.height - spacing.height);
  1548.         }
  1549.         return cellFrame;
  1550.     }
  1551.  
  1552.     /**
  1553.      * This method will resize one or more columns of the table
  1554.      * so that the sum width of all columns will equal to the
  1555.      * width of the table.  If <I>lastColumnOnly</I> is true, then
  1556.      * it will try to resize the last column only to make it fit,
  1557.      * but if it runs into either the minimum size limit of the column
  1558.      * or maximum size limit, then it will change the next to last column also,
  1559.      * etc.  If <I>lastColumnOnly</I> is false, then it will spread the
  1560.      * size delta proportionately to all the columns, while respecting
  1561.      * each column's max and min size limits.  Also, notifications of each
  1562.      * column width change will be sent out as they are resized.  <p>
  1563.      *
  1564.      * Note: It is possible that even after this method is called,
  1565.      *   the total width of the columns is still not be equal to the width
  1566.      *   of the table.  eg. A table with a single column, the column has a
  1567.      *   minimum width of 20, and the tableView has a width of 10.  And there
  1568.      *   is nothing I can do about that.
  1569.      *
  1570.      * @param lastColumnOnly    Try to change the last column only if true
  1571.      * @see TableColumn#setWidth()
  1572.      */
  1573.     public void sizeColumnsToFit(boolean lastColumnOnly) {
  1574.         int intercellWidth = getColumnModel().getColumnMargin();
  1575.         int frameWidth = getWidth();
  1576.         int totalColumnWidth = 0;
  1577.         TableColumn aColumn;
  1578.         int index = 0;
  1579.         int[] columnWidths = new int[this.getColumnCount()];
  1580.         int[] columnMaxWidths = new int[this.getColumnCount()];
  1581.         int[] columnMinWidths = new int[this.getColumnCount()];
  1582.         int maxColumnDelta;
  1583.  
  1584.         // Fetch all the column width related info and put them in my int arrays
  1585.         Enumeration enumeration = getColumnModel().getColumns();
  1586.         while (enumeration.hasMoreElements()) {
  1587.             aColumn = (TableColumn)enumeration.nextElement();
  1588.             columnWidths[index] = aColumn.getWidth();
  1589.             columnMaxWidths[index] = aColumn.getMaxWidth();
  1590.             columnMinWidths[index] = aColumn.getMinWidth();
  1591.             totalColumnWidth += aColumn.getWidth() + intercellWidth;
  1592.             index++;
  1593.         }
  1594.  
  1595.         // What's the amount of space we must grow or shrink by
  1596.         int delta = frameWidth - totalColumnWidth;
  1597.  
  1598.         if ((-1 <= delta) && (delta <= 1))
  1599.             return;                     // Too small to worry about
  1600.  
  1601.         // Ok, we can now adjust the values in my columnWidths[] array to reflect
  1602.         // the new desired width.
  1603.         if (lastColumnOnly) {
  1604.             // The basic idea if lastColumnOnly is true is we start with
  1605.             // the last column adjust the width up or down.  If we hit
  1606.             // a max or min limit than we take the reminder and apply that
  1607.             // to the next to last column.  Repeat as needed.
  1608.             for (index = this.getColumnCount() - 1; index >= 0; index--) {
  1609.                 if (delta > 0) {
  1610.                     // We are growing the column
  1611.                     maxColumnDelta = columnMaxWidths[index] - columnWidths[index];
  1612.                 }
  1613.                 else {
  1614.                     // Shrinking.  Note the maxColumnDelta is going to be negative.
  1615.                     maxColumnDelta = columnMinWidths[index] - columnWidths[index];
  1616.                 }
  1617.  
  1618.                 if (Math.abs(maxColumnDelta) >= Math.abs(delta)) {
  1619.                     columnWidths[index] += delta;
  1620.                     break;
  1621.                 }
  1622.                 else {
  1623.                     columnWidths[index] += maxColumnDelta;
  1624.                     delta -= maxColumnDelta;
  1625.                 }
  1626.             }
  1627.         }
  1628.         else {
  1629.             // We have to spread the delta across all the columns.  To do this
  1630.             // simply and safely, we calculate a percentage value for each
  1631.             // iteration across all the columns.
  1632.  
  1633.             float[] percentShare = new float[this.getColumnCount()];
  1634.             boolean stillHaveRoom = true;
  1635.  
  1636.             // Lets compute the percentShare of the delta that each column
  1637.             // should take up, before we change any columns.
  1638.             // Note: the sum of all the percentages in the array should be 100
  1639.             for (index = 0; index < this.getColumnCount(); index++) {
  1640.                 percentShare[index] = ((float)(columnWidths[index]+intercellWidth) /
  1641.                                        ((float)totalColumnWidth));
  1642.             }
  1643.  
  1644.  
  1645.             // Now we will iterate 1 or more times to distribute the delta,
  1646.             // stopping when delta reaches zero. Unless none of the columns
  1647.             // can change any more because they have all hit their bound limits.
  1648.             // In which case, we also stop.
  1649.             while ((delta != 0) && stillHaveRoom) {
  1650.                 int deltaRemainder = delta;
  1651.                 stillHaveRoom = false;
  1652.  
  1653.                 for (index = 0; index < this.getColumnCount(); index++) {
  1654.                     int shareDelta = (int)Math.ceil((float)delta * percentShare[index]);
  1655.  
  1656.                     // Have to check if deltaRemainder is zero here, if it
  1657.                     // is then we break.  This is needed because we are
  1658.                     // computing the shareDelta using ints which can lead
  1659.                     // to some funny cases with small deltas. eg. a table
  1660.                     // with 6 equal sized columns, and the delta is 2.
  1661.                     // Leading to each column's share being 0.33.  If I round
  1662.                     // down then every column's shareDelta is 0, and the
  1663.                     // loop will never end.  So what I have choose to do
  1664.                     // is take the ceiling.  In the example above, then
  1665.                     // the first column gets 1, and the second also gets
  1666.                     // 1, bring the deltaRemainder to 0, and we should
  1667.                     // stop.
  1668.                     if (deltaRemainder == 0) {
  1669.                         break;
  1670.                     }
  1671.                     else if (Math.abs(deltaRemainder) < Math.abs(shareDelta)) {
  1672.                         // Here we are making sure we don't go over our
  1673.                         // delta because of the ceiling. eg. we have a delta
  1674.                         // of 27.  The 3 column's share computes to 10.2, 10.2,
  1675.                         // and 6.6.  When rounded up becomes 11, 11, 7, which
  1676.                         // adds up to 29.  This check will make the last column's
  1677.                         // share equal to 5.
  1678.                         shareDelta = deltaRemainder;
  1679.                     }
  1680.  
  1681.                     if (shareDelta > 0) {
  1682.                         // We are growing the column
  1683.                         maxColumnDelta = columnMaxWidths[index] - columnWidths[index];
  1684.                     }
  1685.                     else if (shareDelta < 0) {
  1686.                         // Shrinking.  Note the maxColumnDelta is going to be negative.
  1687.                         maxColumnDelta = columnMinWidths[index] - columnWidths[index];
  1688.                     }
  1689.                     else {
  1690.                         // My share is zero, so do nothing.
  1691.                         continue;
  1692.                     }
  1693.  
  1694.                     if (Math.abs(maxColumnDelta) >= Math.abs(shareDelta)) {
  1695.                         stillHaveRoom = true;
  1696.                         columnWidths[index] += shareDelta;
  1697.                         deltaRemainder -= shareDelta;
  1698.                     }
  1699.                     else if (maxColumnDelta != 0) {
  1700.                         columnWidths[index] += maxColumnDelta;
  1701.                         deltaRemainder -= maxColumnDelta;
  1702.  
  1703.                         // I've hit my limits, so I'm going to mark this
  1704.                         // by changing my percentShare to zero
  1705.                         percentShare[index] = 0;
  1706.                     }
  1707.                 }
  1708.  
  1709.                 // Update local vars for next loop iteration
  1710.                 delta = deltaRemainder;         // It is important that delta not
  1711.                                                 // change in the for loop above
  1712.  
  1713.                 if (delta != 0) {
  1714.                     // We have to loop again because one or more columns
  1715.                     // couldn't take their full share of the delta.  And because
  1716.                     // those columns can't take any more in the next iteration,
  1717.                     // their percentShare number has been set to zero.  Now the
  1718.                     // sum total of all the percentShares is less than 100%.
  1719.                     // So we are going to adjust the percent shares so their sum
  1720.                     // total is once again 100%.  Otherwise, the loop will take
  1721.                     // a long time to end, and we'll just get closer and closer
  1722.                     // in many iterations before reaching some where near zero.
  1723.  
  1724.                     float adjustment, percentLeft = 0;
  1725.                     for (index = 0; index < this.getColumnCount(); index++) {
  1726.                         percentLeft += percentShare[index];
  1727.                     }
  1728.                     adjustment = 100 / percentLeft;
  1729.                     for (index = 0; index < this.getColumnCount(); index++) {
  1730.                         percentShare[index] *= adjustment;
  1731.                     }
  1732.                 }
  1733.             }
  1734.         }
  1735.  
  1736.         // Now we really set the widths based on the final value of the array
  1737.         index = 0;
  1738.         enumeration = getColumnModel().getColumns();
  1739.         while (enumeration.hasMoreElements()) {
  1740.             aColumn = (TableColumn)enumeration.nextElement();
  1741.             aColumn.setWidth(columnWidths[index]);
  1742.             index++;
  1743.         }
  1744.     }
  1745.  
  1746.     /**
  1747.      * Overrides JComponent's setToolTipText method to allow use of the
  1748.      * renderer's tips (if the renderer has text set).
  1749.      * <p>
  1750.      * NOTE: For JTable to properly display tooltips of its renderers
  1751.      *       JTable must be a registered component with the ToolTipManager.
  1752.      *       This is done automatically in initializeLocalVars(), but
  1753.      *       if at a later point JTable is told setToolTipText(null)
  1754.      *       it will unregister the table component, and no tips from
  1755.      *       renderers will display anymore.
  1756.      *
  1757.      * @see JComponent#getToolTipText
  1758.      */
  1759.     public String getToolTipText(MouseEvent event) {
  1760.         String tip = null;
  1761.         Point p = event.getPoint();
  1762.  
  1763.         // Locate the renderer under the event location
  1764.         int hitColumnIndex = columnAtPoint(p);
  1765.         int hitRowIndex = rowAtPoint(p);
  1766.  
  1767.         if ((hitColumnIndex != -1) && (hitRowIndex != -1)) {
  1768.             TableColumn aColumn = getColumnModel().getColumn(hitColumnIndex);
  1769.             TableCellRenderer renderer = aColumn.getCellRenderer();
  1770.             if (renderer == null) {
  1771.                 Class columnClass = getColumnClass(hitColumnIndex);
  1772.                 renderer = getDefaultRenderer(columnClass);
  1773.             }
  1774.             Component component = renderer.getTableCellRendererComponent(
  1775.                               this, null, false, false,
  1776.                               hitRowIndex, hitColumnIndex);
  1777.  
  1778.             // Now have to see if the component is a JComponent before
  1779.             // getting the tip
  1780.             if (component instanceof JComponent) {
  1781.                 // Convert the event to the renderer's coordinate system
  1782.                 MouseEvent newEvent;
  1783.                 Rectangle cellRect = getCellRect(hitRowIndex, hitColumnIndex, false);
  1784.  
  1785.                 p.translate(-cellRect.x, -cellRect.y);
  1786.                 newEvent = new MouseEvent(component, event.getID(),
  1787.                                           event.getWhen(), event.getModifiers(),
  1788.                                           p.x, p.y, event.getClickCount(),
  1789.                                           event.isPopupTrigger());
  1790.  
  1791.                 tip = ((JComponent)component).getToolTipText(newEvent);
  1792.             }
  1793.         }
  1794.  
  1795.         // No tip from the renderer get our own tip
  1796.         if (tip == null)
  1797.             tip = getToolTipText();
  1798.  
  1799.         return tip;
  1800.     }
  1801.  
  1802. //
  1803. // Editing Support
  1804. //
  1805.  
  1806.     /**
  1807.      * Programmatically starts editing the cell at <I>row</I> and
  1808.      * <I>column</I>, if the cell is editable.
  1809.      *
  1810.      * @param   row                             the row to be edited
  1811.      * @param   column                          the column to be edited
  1812.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1813.      *                                          are not in the valid range
  1814.      * @return  false if for any reason the cell cannot be edited.
  1815.      */
  1816.     public boolean editCellAt(int row, int column) {
  1817.         return editCellAt(row, column, null);
  1818.     }
  1819.  
  1820.     /**
  1821.      * Programmatically starts editing the cell at <I>row</I> and
  1822.      * <I>column</I>, if the cell is editable.
  1823.      * To prevent the JTable from editing a particular table, column or
  1824.      * cell value, return false from the isCellEditable() method in the
  1825.      * TableModel interface.
  1826.      *
  1827.      * @param   row                             the row to be edited
  1828.      * @param   column                          the column to be edited
  1829.      * @param   e                               event to pass into
  1830.      *                                          shouldSelectCell
  1831.      * @exception IllegalArgumentException      If <I>row</I> or <I>column</I>
  1832.      *                                          are not in the valid range
  1833.      * @return  false if for any reason the cell cannot be edited.
  1834.      */
  1835.     public boolean editCellAt(int row, int column, EventObject e){
  1836.         if (!isCellEditable(row, column))
  1837.             return false;
  1838.  
  1839.         if (isEditing()) {
  1840.             // Try to stop the current editor
  1841.             if (cellEditor != null) {
  1842.                 boolean stopped = cellEditor.stopCellEditing();
  1843.                 if (!stopped)
  1844.                     return false;       // The current editor not resigning
  1845.             }
  1846.         }
  1847.  
  1848.         TableColumn tableColumn = getColumnModel().getColumn(column);
  1849.         TableCellEditor editor = tableColumn.getCellEditor();
  1850.         if (editor == null) {
  1851.             editor = getDefaultEditor(getColumnClass(column));
  1852.         }
  1853.  
  1854.         if (editor != null) {
  1855.             // prepare editor - size it then added it to the table
  1856.             editorComp = prepareEditor(editor, row, column);
  1857.  
  1858.             if (editor.isCellEditable(e)) {
  1859.                 editorComp.setBounds(getCellRect(row, column, false));// PENDING(philip)
  1860.                 this.add(editorComp);
  1861.                 editorComp.validate();
  1862.  
  1863.                 // PENDING: this could convert event at this point!
  1864.                 boolean shouldSelect = editor.shouldSelectCell(e);
  1865.  
  1866.                 setCellEditor(editor);
  1867.                 setEditingRow(row);
  1868.                 setEditingColumn(column);
  1869.                 editor.addCellEditorListener(this);
  1870.  
  1871.                 repaint();
  1872.                 return true;
  1873.             }
  1874.         }
  1875.         return false;
  1876.     }
  1877.  
  1878.     /**
  1879.      * Returns  true is the table is editing a cell.
  1880.      *
  1881.      * @return  true is the table is editing a cell
  1882.      * @see     #editingColumn()
  1883.      * @see     #editingRow()
  1884.      */
  1885.     public boolean isEditing() {
  1886.         return (cellEditor == null)? false : true;
  1887.     }
  1888.  
  1889.     /**
  1890.      * If the receiver is currently editing this will return the Component
  1891.      * that was returned from the CellEditor.
  1892.      *
  1893.      * @return  Component handling editing session
  1894.      */
  1895.     public Component getEditorComponent() {
  1896.         return editorComp;
  1897.     }
  1898.  
  1899.     /**
  1900.      * This returns the index of the editing column.
  1901.      *
  1902.      * @return  the index of the column being edited
  1903.      * @see #editingRow()
  1904.      */
  1905.     public int getEditingColumn() {
  1906.         return editingColumn;
  1907.     }
  1908.  
  1909.     /**
  1910.      * Returns the index of the editing row.
  1911.      *
  1912.      * @return  the index of the row being edited
  1913.      * @see #editingColumn()
  1914.      */
  1915.     public int getEditingRow() {
  1916.         return editingRow;
  1917.     }
  1918.  
  1919. //
  1920. // Managing TableUI
  1921. //
  1922.  
  1923.     /**
  1924.      * Returns the L&F object that renders this component.
  1925.      *
  1926.      * @return the TableUI object that renders this component
  1927.      */
  1928.     public TableUI getUI() {
  1929.         return (TableUI)ui;
  1930.     }
  1931.  
  1932.     /**
  1933.      * Sets the L&F object that renders this component.
  1934.      *
  1935.      * @param ui  the TableUI L&F object
  1936.      * @see UIDefaults#getUI
  1937.      */
  1938.     public void setUI(TableUI ui) {
  1939.         if (this.ui != ui) {
  1940.             super.setUI(ui);
  1941.             repaint();
  1942.         }
  1943.     }
  1944.  
  1945.     private void updateSubComponentUI(Object componentShell) {
  1946.         if (componentShell == null) {
  1947.             return;
  1948.         }
  1949.         Component component = null;
  1950.         if (componentShell instanceof Component) {
  1951.             component = (Component)componentShell;
  1952.         }
  1953.         if (componentShell instanceof DefaultCellEditor) {
  1954.             component = ((DefaultCellEditor)componentShell).getComponent();
  1955.         }
  1956.  
  1957.         if (component != null && component instanceof JComponent) {
  1958.             ((JComponent)component).updateUI();
  1959.         }
  1960.     }
  1961.  
  1962.     /**
  1963.      * Notification from the UIManager that the L&F has changed.
  1964.      * Replaces the current UI object with the latest version from the
  1965.      * UIManager.
  1966.      *
  1967.      * @see JComponent#updateUI
  1968.      */
  1969.     public void updateUI() {
  1970.         // Update the UIs of the cell renderers, cell editors and header renderers.
  1971.         TableColumnModel cm = getColumnModel();
  1972.         for(int column = 0; column < cm.getColumnCount(); column++) {
  1973.             TableColumn aColumn = cm.getColumn(column);
  1974.            // updateSubComponentUI(aColumn.getCellRenderer());
  1975.             updateSubComponentUI(aColumn.getCellEditor());
  1976.            // updateSubComponentUI(aColumn.getHeaderRenderer());
  1977.         }
  1978.  
  1979.         // Update the UIs of all the default renderers.
  1980.         /*
  1981.         Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
  1982.         while (defaultRenderers.hasMoreElements()) {
  1983.             updateSubComponentUI(defaultRenderers.nextElement());
  1984.         }
  1985.         */
  1986.  
  1987.         // Update the UIs of all the default editors.
  1988.         Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
  1989.         while (defaultEditors.hasMoreElements()) {
  1990.             updateSubComponentUI(defaultEditors.nextElement());
  1991.         }
  1992.  
  1993.         setUI((TableUI)UIManager.getUI(this));
  1994.         resizeAndRepaint();
  1995.         invalidate();//PENDING
  1996.     }
  1997.  
  1998.     /**
  1999.      * Returns the name of the L&F class that renders this component.
  2000.      *
  2001.      * @return "TableUI"
  2002.      * @see JComponent#getUIClassID
  2003.      * @see UIDefaults#getUI
  2004.      */
  2005.     public String getUIClassID() {
  2006.         return "TableUI";
  2007.     }
  2008.  
  2009.  
  2010. //
  2011. // Managing models
  2012. //
  2013.  
  2014.     /**
  2015.      * Sets the data model for this table to <I>newModel</I> and registers
  2016.      * with for listner notifications from the new data model.
  2017.      *
  2018.      * @param   newModel        the new data source for this table
  2019.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  2020.      * @see     #getModel()
  2021.      * @beaninfo
  2022.      * description: The model that is the source of the data for this view.
  2023.      */
  2024.     public void setModel(TableModel newModel) {
  2025.         TableModel oldModel = dataModel;
  2026.  
  2027.         if (newModel == null)
  2028.             throw new IllegalArgumentException("Cannot set a null TableModel");
  2029.  
  2030.         if (newModel != oldModel) {
  2031.             if (oldModel != null)
  2032.                 oldModel.removeTableModelListener(this);
  2033.             dataModel = newModel;
  2034.             newModel.addTableModelListener(this);
  2035.             // If this method is called from the JTable constructor,
  2036.             // the column model will be null. In this case we can't use
  2037.             // the usual methods to update the internal state. In all other
  2038.             // cases, use the usual tableChanged() method to reconfigure
  2039.             // the JTable for the new model.
  2040.             if (getColumnModel() != null) {
  2041.                 tableChanged(new TableModelEvent(dataModel, TableModelEvent.HEADER_ROW));
  2042.             }
  2043.         }
  2044.     }
  2045.  
  2046.     /**
  2047.      * Returns the <B>TableModel</B> that provides the data displayed by
  2048.      * the receiver.
  2049.      *
  2050.      * @return  the object that provides the data displayed by the receiver
  2051.      * @see     #setModel()
  2052.      */
  2053.     public TableModel getModel() {
  2054.         return dataModel;
  2055.     }
  2056.  
  2057.     /**
  2058.      * Sets the column model for this table to <I>newModel</I> and registers
  2059.      * with for listner notifications from the new column model. Also sets
  2060.      * the column model of the JTableHeader to <I>newModel</I>.
  2061.      *
  2062.      * @param   newModel        the new data source for this table
  2063.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  2064.      * @see     #getColumnModel()
  2065.      * @beaninfo
  2066.      * description: The object governing the way columns appear in the view.
  2067.      */
  2068.     public void setColumnModel(TableColumnModel newModel) {
  2069.         if (newModel == null) {
  2070.             throw new IllegalArgumentException("Cannot set a null ColumnModel");
  2071.         }
  2072.  
  2073.         TableColumnModel oldModel = columnModel;
  2074.         if (newModel != oldModel) {
  2075.             if (oldModel != null)
  2076.                 oldModel.removeColumnModelListener(this);
  2077.  
  2078.             columnModel = newModel;
  2079.             newModel.addColumnModelListener(this);
  2080.  
  2081.  
  2082.             // Set the column model of the header as well.
  2083.             if (tableHeader != null) {
  2084.                 tableHeader.setColumnModel(newModel);
  2085.             }
  2086.  
  2087.             resizeAndRepaint();
  2088.         }
  2089.     }
  2090.  
  2091.     /**
  2092.      * Returns the <B>TableColumnModel</B> that contains all column inforamtion
  2093.      * of this table.
  2094.      *
  2095.      * @return  the object that provides the column state of the table
  2096.      * @see     #setColumnModel()
  2097.      */
  2098.     public TableColumnModel getColumnModel() {
  2099.         return columnModel;
  2100.     }
  2101.  
  2102.     /**
  2103.      * Sets the row selection model for this table to <I>newModel</I>
  2104.      * and registers with for listner notifications from the new selection model.
  2105.      *
  2106.      * @param   newModel        the new selection model
  2107.      * @exception IllegalArgumentException      if <I>newModel</I> is null
  2108.      * @see     #getSelectionModel()
  2109.      * @beaninfo
  2110.      * description: The selection model for rows.
  2111.      */
  2112.     public void setSelectionModel(ListSelectionModel newModel) {
  2113.         if (newModel == null) {
  2114.             throw new IllegalArgumentException("Cannot set a null SelectionModel");
  2115.         }
  2116.  
  2117.         ListSelectionModel oldModel = selectionModel;
  2118.  
  2119.         if (newModel != oldModel) {
  2120.             if (oldModel != null) {
  2121.                 oldModel.removeListSelectionListener(this);
  2122.             }
  2123.  
  2124.             selectionModel = newModel;
  2125.  
  2126.             if (newModel != null) {
  2127.                 newModel.addListSelectionListener(this);
  2128.             }
  2129.             repaint();
  2130.         }
  2131.     }
  2132.  
  2133.     /**
  2134.      * Returns the <B>ListSelectionModel</B> that is used to maintain row
  2135.      * selection state.
  2136.      *
  2137.      * @return  the object that provides row selection state.  Or <B>null</B>
  2138.      *          if row selection is not allowed.
  2139.      * @see     #setSelectionModel()
  2140.      */
  2141.     public ListSelectionModel getSelectionModel() {
  2142.         return selectionModel;
  2143.     }
  2144.  
  2145. //
  2146. // Implementing TableModelListener interface
  2147. //
  2148.  
  2149.     /**
  2150.      * The TableModelEvent should be constructed in the co-ordinate system
  2151.      * of the model, the appropriate mapping to the view co-ordinate system
  2152.      * is performed by the JTable when it recieves the event.
  2153.      */
  2154.     public void tableChanged(TableModelEvent e) {
  2155.         if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW) {
  2156.             // The whole thing changed
  2157.             clearSelection();
  2158.  
  2159.             if (getAutoCreateColumnsFromModel())
  2160.                 createDefaultColumnsFromModel();
  2161.  
  2162.             resizeAndRepaint();
  2163.             if (tableHeader != null) {
  2164.                 tableHeader.resizeAndRepaint();
  2165.             }
  2166.             return;
  2167.         }
  2168.  
  2169.         if (e.getType() == TableModelEvent.INSERT) {
  2170.             tableRowsInserted(e);
  2171.             return;
  2172.         }
  2173.  
  2174.         if (e.getType() == TableModelEvent.DELETE) {
  2175.             tableRowsDeleted(e);
  2176.             return;
  2177.         }
  2178.  
  2179.         int modelColumn = e.getColumn();
  2180.         int start = e.getFirstRow();
  2181.         int end = e.getLastRow();
  2182.  
  2183.         if (start == TableModelEvent.HEADER_ROW) {
  2184.             start = 0;
  2185.             end = Integer.MAX_VALUE;
  2186.         }
  2187.  
  2188.         int rowHeight = getRowHeight() + rowMargin;
  2189.         Rectangle dirtyRegion;
  2190.         if (modelColumn == TableModelEvent.ALL_COLUMNS) {
  2191.             // 1 or more rows changed
  2192.             dirtyRegion = new Rectangle(0, start * rowHeight,
  2193.                                         getColumnModel().getTotalColumnWidth(), 0);
  2194.         }
  2195.         else {
  2196.             // A cell or column of cells has changed.
  2197.             // Unlike the rest of the methods in the JTable, the TableModelEvent
  2198.             // uses the co-ordinate system of the model instead of the view.
  2199.             // This is the only place in the JTable where this "reverse mapping"
  2200.             // is used.
  2201.             int column = convertColumnIndexToView(modelColumn);
  2202.             dirtyRegion = getCellRect(start, column, false);
  2203.         }
  2204.  
  2205.         // Now adjust the height of the dirty region according to the value of "end".
  2206.         // Check for Integer.MAX_VALUE as this will cause an overflow.
  2207.         if (end != Integer.MAX_VALUE) {
  2208.             dirtyRegion.height = (end-start+1)*rowHeight;
  2209.             repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2210.         }
  2211.         // In fact, if the end is Integer.MAX_VALUE we need to revalidate anyway
  2212.         // because the scrollbar may need repainting.
  2213.         else {
  2214.             resizeAndRepaint();
  2215.         }
  2216.     }
  2217.  
  2218.     /*
  2219.      * Invoked when rows have been inserted into the table.
  2220.      *
  2221.      * @param e the TableModelEvent encapsulating the insertion
  2222.      */
  2223.     private void tableRowsInserted(TableModelEvent e) {
  2224.         int start = e.getFirstRow();
  2225.         if (start < 0)
  2226.             start = 0;
  2227.  
  2228.         // 1 or more rows added, so I have to repaint from the first
  2229.         // new row to the end of the table.  (Everything shifts down)
  2230.         int rowHeight = getRowHeight() + rowMargin;
  2231.         Rectangle drawRect = new Rectangle(0, start * rowHeight,
  2232.                                         getColumnModel().getTotalColumnWidth(),
  2233.                                            (getRowCount()-start) * rowHeight);
  2234.  
  2235.         // Adjust the selection to account for the new rows
  2236.         if (selectionModel != null) {
  2237.             int end = e.getLastRow();
  2238.             if (end < 0)
  2239.                 end = getRowCount()-1;
  2240.             int length = end - start + 1;
  2241.  
  2242.             selectionModel.insertIndexInterval(start, length, true);
  2243.         }
  2244.         revalidate();
  2245.         repaint(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
  2246.     }
  2247.  
  2248.     /*
  2249.      * Invoked when rows have been removed from the table.
  2250.      *
  2251.      * @param e the TableModelEvent encapsulating the deletion
  2252.      */
  2253.     private void tableRowsDeleted(TableModelEvent e) {
  2254.         int start = e.getFirstRow();
  2255.         if (start < 0)
  2256.             start = 0;
  2257.  
  2258.         // 1 or more rows added, so I have to repaint from the first
  2259.         // new row to the end of the table.  (Everything shifts down)
  2260.         int rowHeight = getRowHeight() + rowMargin;
  2261.         Rectangle drawRect = new Rectangle(0, start * rowHeight,
  2262.                                         getColumnModel().getTotalColumnWidth(),
  2263.                                            (getRowCount()-start) * rowHeight);
  2264.  
  2265.         // Adjust the selection to account for the new rows
  2266.         if (selectionModel != null) {
  2267.             int end = e.getLastRow();
  2268.             if (end < 0)
  2269.                 end = getRowCount()-1;
  2270.  
  2271.             selectionModel.removeIndexInterval(start, end);
  2272.         }
  2273.         revalidate();
  2274.         repaint(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
  2275.     }
  2276.  
  2277. //
  2278. // Implementing TableColumnModelListener interface
  2279. //
  2280.  
  2281.     /**
  2282.      * Tells listeners that a column was added to the model.
  2283.      *
  2284.      * @see TableColumnModelListener
  2285.      */
  2286.     public void columnAdded(TableColumnModelEvent e) {
  2287.         // If I'm currently editing, then I should stop editing
  2288.         if (isEditing()) {
  2289.             removeEditor();
  2290.         }
  2291.         resizeAndRepaint();
  2292.     }
  2293.  
  2294.     /**
  2295.      * Tells listeners that a column was removed from the model.
  2296.      *
  2297.      * @see TableColumnModelListener
  2298.      */
  2299.     public void columnRemoved(TableColumnModelEvent e) {
  2300.         // If I'm currently editing, then I should stop editing
  2301.         if (isEditing()) {
  2302.             removeEditor();
  2303.         }
  2304.         resizeAndRepaint();
  2305.     }
  2306.  
  2307.     /**
  2308.      * Tells listeners that a column was repositioned.
  2309.      *
  2310.      * @see TableColumnModelListener
  2311.      */
  2312.     public void columnMoved(TableColumnModelEvent e) {
  2313.         // If I'm currently editing, then I should stop editing
  2314.         if (isEditing()) {
  2315.             removeEditor();
  2316.         }
  2317.         repaint();
  2318.     }
  2319.  
  2320.     /**
  2321.      * Tells listeners that a column was moved due to a margin change.
  2322.      *
  2323.      * @see TableColumnModelListener
  2324.      */
  2325.     public void columnMarginChanged(ChangeEvent e) {
  2326.         // If I'm currently editing, then I should stop editing
  2327.         if (isEditing()) {
  2328.             removeEditor();
  2329.         }
  2330.         resizeAndRepaint();
  2331.     }
  2332.  
  2333.     /**
  2334.      * Tells listeners that the selection model of the
  2335.      * TableColumnModel changed.
  2336.      *
  2337.      * @see TableColumnModelListener
  2338.      */
  2339.     public void columnSelectionChanged(ListSelectionEvent e) {
  2340.         int firstIndex = e.getFirstIndex();
  2341.         int lastIndex = e.getLastIndex();
  2342.         if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
  2343.             repaint();
  2344.         }
  2345.         Rectangle firstColumnRect = getCellRect(0, firstIndex, false);
  2346.         Rectangle lastColumnRect = getCellRect(getRowCount(), lastIndex, false);
  2347.         Rectangle dirtyRegion = firstColumnRect.union(lastColumnRect);
  2348.         // This marks this entire column as dirty but the painting system will
  2349.         // intersect this with the clip rect of the viewport and redraw only
  2350.         // the visible cells.
  2351.         repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2352.     }
  2353.  
  2354. //
  2355. // Implementing ListSelectionListener interface
  2356. //
  2357.  
  2358.     /**
  2359.      * Tells listeners that the selection changed.
  2360.      *
  2361.      * @see ListSelectionListener
  2362.      */
  2363.     public void valueChanged(ListSelectionEvent e) {
  2364.         int firstIndex = e.getFirstIndex();
  2365.         int lastIndex = e.getLastIndex();
  2366.         if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
  2367.             repaint();
  2368.         }
  2369.         Rectangle firstRowRect = getCellRect(firstIndex, 0, false);
  2370.         Rectangle lastRowRect = getCellRect(lastIndex, getColumnCount(), false);
  2371.         Rectangle dirtyRegion = firstRowRect.union(lastRowRect);
  2372.         // This marks this entire row as dirty but the painting system will
  2373.         // intersect this with the clip rect of the viewport and redraw only
  2374.         // the visible cells.
  2375.         repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
  2376.     }
  2377.  
  2378. //
  2379. // Implementing the CellEditorListener interface
  2380. //
  2381.  
  2382.     /**
  2383.      * Invoked when editing is finished. The changes are saved, the
  2384.      * editor object is discarded, and the cell is rendered once again.
  2385.      *
  2386.      * @see CellEditorListener
  2387.      */
  2388.     public void editingStopped(ChangeEvent e) {
  2389.         // Take in the new value
  2390.         TableCellEditor editor = getCellEditor();
  2391.         if (editor != null) {
  2392.             Object value = editor.getCellEditorValue();
  2393.             setValueAt(value, editingRow, editingColumn);
  2394.  
  2395.             removeEditor();
  2396.         }
  2397.     }
  2398.  
  2399.     /**
  2400.      * Invoked when editing is canceled. The editor object is discarded
  2401.      * and the cell is rendered once again.
  2402.      *
  2403.      * @see CellEditorListener
  2404.      */
  2405.     public void editingCanceled(ChangeEvent e) {
  2406.         removeEditor();
  2407.     }
  2408.  
  2409. //
  2410. // Implementing the Scrollable interface
  2411. //
  2412.  
  2413.     /**
  2414.      * Sets the preferred size of the viewport for this table.
  2415.      *
  2416.      * @param size  a Dimension object specifying the preferredSize of a
  2417.      *              JViewport whose view is this table
  2418.      * @see Scrollable#getPreferredScrollableViewportSize
  2419.      * @beaninfo
  2420.      * description: The preferred size of the viewport.
  2421.      */
  2422.     public void setPreferredScrollableViewportSize(Dimension size) {
  2423.         preferredViewportSize = size;
  2424.     }
  2425.  
  2426.     /**
  2427.      * Returns the preferred size of the viewport for this table.
  2428.      *
  2429.      * @return a Dimension object containing the preferredSize of the JViewport
  2430.      *         which displays this table
  2431.      * @see Scrollable#getPreferredScrollableViewportSize
  2432.      */
  2433.     public Dimension getPreferredScrollableViewportSize() {
  2434.         return preferredViewportSize;
  2435.     }
  2436.  
  2437.     /**
  2438.      * Returns the scroll increment that completely exposes one new row
  2439.      * or column (depending on the orientation).
  2440.      * <p>
  2441.      * This method is called each time the user requests a unit scroll.
  2442.      *
  2443.      * @param visibleRect The view area visible within the viewport
  2444.      * @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
  2445.      * @param direction Less than zero to scroll up/left, greater than zero for down/right.
  2446.      * @return The "unit" increment for scrolling in the specified direction
  2447.      * @see Scrollable#getScrollableUnitIncrement
  2448.      */
  2449.     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
  2450.                                           int direction) {
  2451.         // PENDING(alan): do something smarter
  2452.         if (orientation == SwingConstants.HORIZONTAL) {
  2453.             return 1;
  2454.         }
  2455.         return rowHeight;
  2456.     }
  2457.  
  2458.     /**
  2459.      * Returns The visibleRect.height or visibleRect.width, depending on the
  2460.      * table's orientation.
  2461.      *
  2462.      * @return The visibleRect.height or visibleRect.width per the orientation.
  2463.      * @see Scrollable#getScrollableBlockIncrement
  2464.      */
  2465.     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
  2466.                                            int direction) {
  2467.         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height :
  2468.             visibleRect.width;
  2469.     }
  2470.  
  2471.     /**
  2472.      * Returns false to indicate that the width of the viewport does not
  2473.      * determine the width of the table.
  2474.      *
  2475.      * @return false
  2476.      * @see Scrollable#getScrollableTracksViewportWidth
  2477.      */
  2478.     public boolean getScrollableTracksViewportWidth() {
  2479.         return false;
  2480.     }
  2481.  
  2482.     /**
  2483.      * Returns false to indicate that the height of the viewport does not
  2484.      * determine the height of the table.
  2485.      *
  2486.      * @return false
  2487.      * @see Scrollable#getScrollableTracksViewportHeight
  2488.      */
  2489.     public boolean getScrollableTracksViewportHeight() {
  2490.         return false;
  2491.     }
  2492.  
  2493. //
  2494. // Protected Methods
  2495. //
  2496.  
  2497.     private class CheckBoxRenderer extends JCheckBox implements TableCellRenderer
  2498.     {
  2499.         public Component getTableCellRendererComponent(JTable table, Object value,
  2500.                          boolean isSelected, boolean hasFocus, int row, int column) {
  2501.             setSelected((value != null && ((Boolean)value).booleanValue()));
  2502.             return this;
  2503.         }
  2504.     }
  2505.  
  2506.     protected void createDefaultRenderers() {
  2507.         defaultRenderersByColumnClass = new Hashtable();
  2508.  
  2509.         // Objects
  2510.         DefaultTableCellRenderer label = new DefaultTableCellRenderer();
  2511.         setDefaultRenderer(Object.class, label);
  2512.  
  2513.         // Numbers
  2514.         DefaultTableCellRenderer rightAlignedLabel = new DefaultTableCellRenderer();
  2515.         rightAlignedLabel.setHorizontalAlignment(JLabel.RIGHT);
  2516.         setDefaultRenderer(Number.class, rightAlignedLabel);
  2517.  
  2518.         // Icons
  2519.         DefaultTableCellRenderer centeredLabel = new DefaultTableCellRenderer() {
  2520.             public void setValue(Object value) { setIcon((Icon)value); }
  2521.         };
  2522.         centeredLabel.setHorizontalAlignment(JLabel.CENTER);
  2523.         setDefaultRenderer(ImageIcon.class, centeredLabel);
  2524.  
  2525.         // Booleans
  2526. /*      DefaultTableCellRenderer booleanRenderer = new DefaultTableCellRenderer() {
  2527.             Icon trueIcon = UIManager.getIcon("CheckBox.icon");
  2528.             public void setValue(Object value) {
  2529.                 setIcon((value != null && ((Boolean)value).booleanValue()) ? trueIcon : null);
  2530.             }
  2531.         };
  2532.         booleanRenderer.setHorizontalAlignment(JLabel.CENTER);
  2533.         setDefaultRenderer(Boolean.class, booleanRenderer);
  2534. */
  2535.         CheckBoxRenderer booleanRenderer = new CheckBoxRenderer();
  2536.         booleanRenderer.setHorizontalAlignment(JLabel.CENTER);
  2537.         setDefaultRenderer(Boolean.class, booleanRenderer);
  2538.     }
  2539.  
  2540.     /**
  2541.      * Creates default cell editors for Objects, numbers, and boolean values.
  2542.      */
  2543.     protected void createDefaultEditors() {
  2544.         defaultEditorsByColumnClass = new Hashtable();
  2545.  
  2546.         // Objects
  2547.         JTextField textField = new JTextField();
  2548.         textField.setBorder(new LineBorder(Color.black));
  2549.         setDefaultEditor(Object.class, new DefaultCellEditor(textField));
  2550.  
  2551.         // Numbers
  2552.         JTextField rightAlignedTextField = new JTextField();
  2553.         rightAlignedTextField.setHorizontalAlignment(JTextField.RIGHT);
  2554.         rightAlignedTextField.setBorder(new LineBorder(Color.black));
  2555.         setDefaultEditor(Number.class, new DefaultCellEditor(rightAlignedTextField));
  2556.  
  2557.         // Booleans
  2558.         JCheckBox centeredCheckBox = new JCheckBox();
  2559.         centeredCheckBox.setHorizontalAlignment(JCheckBox.CENTER);
  2560.         setDefaultEditor(Boolean.class, new DefaultCellEditor(centeredCheckBox));
  2561.     }
  2562.  
  2563.     /**
  2564.      * Initializes table properties to their default values.
  2565.      */
  2566.     protected void initializeLocalVars() {
  2567.         createDefaultRenderers();
  2568.         createDefaultEditors();
  2569.  
  2570.         setTableHeader(createDefaultTableHeader());
  2571.  
  2572.         setShowGrid(true);
  2573.         setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
  2574.         setRowHeight(16);
  2575.         rowMargin = 1;
  2576.         setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  2577.         setColumnSelectionAllowed(false);
  2578.         setRowSelectionAllowed(true);
  2579.         setCellSelectionEnabled(false);
  2580.         cellEditor = null;
  2581.         editingColumn = editingRow = -1;
  2582.         preferredViewportSize = new Dimension(450,400);
  2583.  
  2584.         // I'm registered to do tool tips so we can draw tips for the renderers
  2585.         ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
  2586.         toolTipManager.registerComponent(this);
  2587.  
  2588.         setAutoscrolls(true);
  2589.         tableHeader.setAutoscrolls(true);
  2590.     }
  2591.  
  2592.     /**
  2593.      * Returns the default table model object which is
  2594.      * a DefaultTableModel.  Subclass can override this
  2595.      * method to return a different table model object.
  2596.      *
  2597.      * @return the default table model object
  2598.      */
  2599.     protected TableModel createDefaultDataModel() {
  2600.         return new DefaultTableModel();
  2601.     }
  2602.  
  2603.     /**
  2604.      * Returns the default column model object which is
  2605.      * a DefaultTableColumnModel.  Subclass can override this
  2606.      * method to return a different column model object
  2607.      *
  2608.      * @return the default column model object
  2609.      */
  2610.     protected TableColumnModel createDefaultColumnModel() {
  2611.         return new DefaultTableColumnModel();
  2612.     }
  2613.  
  2614.     /**
  2615.      * Returns the default selection model object which is
  2616.      * a DefaultListSelectionModel.  Subclass can override this
  2617.      * method to return a different selection model object.
  2618.      *
  2619.      * @return the default selection model object
  2620.      */
  2621.     protected ListSelectionModel createDefaultSelectionModel() {
  2622.         DefaultListSelectionModel m = new DefaultListSelectionModel();
  2623.         // By turning this off we get notified of the minimal range of rows
  2624.         // that need to be drawn when the selection changes. This improves
  2625.         // redrawing performance considerably during mouseDragged.
  2626.         m.setLeadAnchorNotificationEnabled(false);
  2627.         return m;
  2628.     }
  2629.  
  2630.     /**
  2631.      * Returns the default table header object which is
  2632.      * a JTableHeader.  Subclass can override this
  2633.      * method to return a different table header object
  2634.      *
  2635.      * @return the default table header object
  2636.      */
  2637.     protected JTableHeader createDefaultTableHeader() {
  2638.         return new JTableHeader(columnModel);
  2639.     }
  2640.  
  2641.     /**
  2642.      * Properly sizes the receiver and its header view, and marks it as
  2643.      * needing display. Also resets cursor rectangles for the header view
  2644.      * and line scroll amounts for the <B>JScrollPane</B>.
  2645.      */
  2646.     protected void resizeAndRepaint() {
  2647.         revalidate();
  2648.         repaint();
  2649.     }
  2650.  
  2651.     /**
  2652.      * Return the cellEditor.
  2653.      *
  2654.      * @return the TableCellEditor that does the editing
  2655.      * @see #cellEditor
  2656.      */
  2657.     public TableCellEditor getCellEditor() {
  2658.         return cellEditor;
  2659.     }
  2660.  
  2661.     /**
  2662.      * Set the cellEditor variable.
  2663.      *
  2664.      * @param anEditor  the TableCellEditor that does the editing
  2665.      * @see #cellEditor
  2666.      */
  2667.     public void setCellEditor(TableCellEditor anEditor) {
  2668.         cellEditor = anEditor;
  2669.     }
  2670.  
  2671.     /**
  2672.      * Set the editingColumn variable.
  2673.      *
  2674.      * @see #editingColumn
  2675.      */
  2676.     public void setEditingColumn(int aColumn) {
  2677.         editingColumn = aColumn;
  2678.     }
  2679.  
  2680.     /**
  2681.      * Set the editingRow variable.
  2682.      *
  2683.      * @see #editingRow
  2684.      */
  2685.     public void setEditingRow(int aRow) {
  2686.         editingRow = aRow;
  2687.     }
  2688.  
  2689.     /**
  2690.      * Returns true to indicate that this component paints every pixel
  2691.      * in its range. (In other words, it does not have a transparent
  2692.      * background or foreground.)
  2693.      *
  2694.      * @return true
  2695.      * @see JComponent#isOpaque
  2696.      */
  2697.     public boolean isOpaque() {
  2698.         return true;
  2699.     }
  2700.  
  2701.     /**
  2702.      * Sets up the specified editor using the value at the specified cell.
  2703.      *
  2704.      * @param editor  the TableCellEditor to set up
  2705.      * @param row     the row of the cell to edit, where 0 is the first
  2706.      * @param column  the column of the cell to edit, where 0 is the first
  2707.      */
  2708.     public Component prepareEditor(TableCellEditor editor,
  2709.                                    int row, int column) {
  2710.         Object value = getValueAt(row, column);
  2711.  
  2712.         TableColumn tableColumn = getColumnModel().getColumn(column);
  2713.         boolean isSelected = isCellSelected(row, column);
  2714.         Component comp = editor.getTableCellEditorComponent(this, value, isSelected,
  2715.                                                   row, column);
  2716.         if((comp != null) && (comp.getFont() == null)) {
  2717.             comp.setFont(getFont());
  2718.         }
  2719.         return comp;
  2720.     }
  2721.  
  2722.     /**
  2723.      * Discard the editor object and return the real estate it used to
  2724.      * cell rendering.
  2725.      */
  2726.     public void removeEditor() {
  2727.         TableCellEditor editor = getCellEditor();
  2728.         if(editor != null) {
  2729.             editor.removeCellEditorListener(this);
  2730.  
  2731.             // PENDING(alan): This is a temp work around for a JComboBox bug
  2732.             if (editorComp instanceof JComboBox) {
  2733.                 ((JComboBox)editorComp).hidePopup();
  2734.             }
  2735.  
  2736.             remove(editorComp);
  2737.             Rectangle cellRect = getCellRect(editingRow, editingColumn, false);
  2738.             repaint(cellRect.x, cellRect.y,
  2739.                     cellRect.width, cellRect.height);
  2740.  
  2741.             if (!(editorComp instanceof JComponent) ||
  2742.                  ((JComponent)editorComp).hasFocus()) {
  2743.                 requestFocus();
  2744.             }
  2745.  
  2746.             setCellEditor(null);
  2747.             setEditingColumn(-1);
  2748.             setEditingRow(-1);
  2749.             editorComp = null;
  2750.         }
  2751.     }
  2752.  
  2753. //
  2754. // Serialization
  2755. //
  2756.  
  2757.     private void writeObject(ObjectOutputStream s) throws IOException {
  2758.         s.defaultWriteObject();
  2759.     }
  2760.  
  2761.  
  2762.     private void readObject(ObjectInputStream s)
  2763.         throws IOException, ClassNotFoundException
  2764.     {
  2765.         s.defaultReadObject();
  2766.         createDefaultRenderers();
  2767.         createDefaultEditors();
  2768.     }
  2769.  
  2770. /////////////////
  2771. // Accessibility support
  2772. ////////////////
  2773.  
  2774.     /**
  2775.      * Get the AccessibleContext associated with this JComponent
  2776.      *
  2777.      * @return the AccessibleContext of this JComponent
  2778.      */
  2779.     public AccessibleContext getAccessibleContext() {
  2780.         if (accessibleContext == null) {
  2781.             accessibleContext = new AccessibleJTable();
  2782.         }
  2783.         return accessibleContext;
  2784.     }
  2785.  
  2786.     //
  2787.     // *** should also implement AccessibleSelction?
  2788.     // *** and what's up with keyboard navigation/manipulation?
  2789.     //
  2790.     /**
  2791.      * The class used to obtain the accessible role for this object.
  2792.      * <p>
  2793.      * Warning: serialized objects of this class will not be compatible with
  2794.      * future swing releases.  The current serialization support is appropriate
  2795.      * for short term storage or RMI between Swing1.0 applications.  It will
  2796.      * not be possible to load serialized Swing1.0 objects with future releases
  2797.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  2798.      * baseline for the serialized form of Swing objects.
  2799.      */
  2800.     protected class AccessibleJTable extends AccessibleJComponent {
  2801.  
  2802.         /**
  2803.          * Get the role of this object.
  2804.          *
  2805.          * @return an instance of AccessibleRole describing the role of the
  2806.          * object
  2807.          * @see AccessibleRole
  2808.          */
  2809.         public AccessibleRole getAccessibleRole() {
  2810.             return AccessibleRole.TABLE;
  2811.         }
  2812.  
  2813.         /**
  2814.          * Returns the Accessible child, if one exists, contained at the local
  2815.          * coordinate Point.
  2816.          *
  2817.          * @param p The point defining the top-left corner of the Accessible,
  2818.          * given in the coordinate space of the object's parent.
  2819.          * @return the Accessible, if it exists, at the specified location;
  2820.          * else null
  2821.          */
  2822.         public Accessible getAccessibleAt(Point p) {
  2823.             int column = columnAtPoint(p);
  2824.             int row = rowAtPoint(p);
  2825.  
  2826.             if ((column != -1) && (row != -1)) {
  2827.                 TableColumn aColumn = getColumnModel().getColumn(column);
  2828.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  2829.                 if (renderer == null) {
  2830.                     Class columnClass = getColumnClass(column);
  2831.                     renderer = getDefaultRenderer(columnClass);
  2832.                 }
  2833.                 Component component = renderer.getTableCellRendererComponent(
  2834.                                   JTable.this, null, false, false,
  2835.                                   row, column);
  2836.                 return new AccessibleJTableCell(JTable.this, row, column,
  2837.                       getAccessibleIndexAt(row, column));
  2838.             }
  2839.             return null;
  2840.         }
  2841.  
  2842.         /**
  2843.          * Returns the number of accessible children in the object.  If all
  2844.          * of the children of this object implement Accessible, than this
  2845.          * method should return the number of children of this object.
  2846.          *
  2847.          * @return the number of accessible children in the object.
  2848.          */
  2849.         public int getAccessibleChildrenCount() {
  2850.             return (JTable.this.getColumnCount() * JTable.this.getRowCount());
  2851.         }
  2852.  
  2853.         /**
  2854.          * Return the nth Accessible child of the object.
  2855.          *
  2856.          * @param i zero-based index of child
  2857.          * @return the nth Accessible child of the object
  2858.          */
  2859.         public Accessible getAccessibleChild(int i) {
  2860.             if (i < 0 || i >= getAccessibleChildrenCount()) {
  2861.                 return null;
  2862.             } else {
  2863.                 // children increase across, and then down, for tables
  2864.                 // (arbitrary decision)
  2865.                 int column = getAccessibleColumnAtIndex(i);
  2866.                 int row = getAccessibleRowAtIndex(i);
  2867.  
  2868.                 TableColumn aColumn = getColumnModel().getColumn(column);
  2869.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  2870.                 if (renderer == null) {
  2871.                     Class columnClass = getColumnClass(column);
  2872.                     renderer = getDefaultRenderer(columnClass);
  2873.                 }
  2874.                 Component component = renderer.getTableCellRendererComponent(
  2875.                                   JTable.this, null, false, false,
  2876.                                   row, column);
  2877.                 return new AccessibleJTableCell(JTable.this, row, column,
  2878.                       getAccessibleIndexAt(row, column));
  2879.             }
  2880.         }
  2881.  
  2882. //        /**
  2883. //         * Get the AccessibleTable associated with this object if one
  2884. //         * exists.  Otherwise return null.
  2885. //         */
  2886. //        public AccessibleTable getAccessibleTable() {
  2887. //            return this;
  2888. //        }
  2889.  
  2890.  
  2891.     // AccessibleTable methods
  2892.  
  2893.         /*
  2894.          * Returns the total number of rows in the table
  2895.          *
  2896.          * @return the total number of rows in the table
  2897.          */
  2898.         private int getAccessibleRowCount() {
  2899.             return JTable.this.getRowCount();
  2900.         }
  2901.  
  2902.         /*
  2903.          * Returns the total number of columns in the table
  2904.          *
  2905.          * @return the total number of columns in the table
  2906.          */
  2907.         private int getAccessibleColumnCount() {
  2908.             return JTable.this.getColumnCount();
  2909.         }
  2910.  
  2911.         /*
  2912.          * Returns the row at a given index into the table
  2913.          *
  2914.          * @param i zero-based index into the table
  2915.          * @return the row at a given index
  2916.          */
  2917.         private int getAccessibleRowAtIndex(int i) {
  2918.             return (i / getAccessibleColumnCount());
  2919.         }
  2920.  
  2921.         /*
  2922.          * Returns the column at a given index into the table
  2923.          *
  2924.          * @param i zero-based index into the table
  2925.          * @return the column at a given index
  2926.          */
  2927.         private int getAccessibleColumnAtIndex(int i) {
  2928.             return (i % getAccessibleColumnCount());
  2929.         }
  2930.  
  2931.         /*
  2932.          * Returns the index at a given (row, column) in the table
  2933.          *
  2934.          * @param r zero-based row of the table
  2935.          * @param c zero-based column of the table
  2936.          * @return the index into the table
  2937.          */
  2938.         private int getAccessibleIndexAt(int r, int c) {
  2939.             return ((r * getAccessibleColumnCount()) + c);
  2940.         }
  2941.  
  2942.         /*
  2943.          * Returns the Accessible at a given (row, column) in the table
  2944.          *
  2945.          * @param r zero-based row of the table
  2946.          * @param c zero-based column of the table
  2947.          * @return the Accessible at the specified (row, column)
  2948.          */
  2949.         private Accessible getAccessibleAt(int r, int c) {
  2950.             return getAccessibleChild((r * getAccessibleColumnCount()) + c);
  2951.         }
  2952.  
  2953.         /*
  2954.          * Return the Accessible representing the row header, if
  2955.          * there is one (may be null).
  2956.          *
  2957.          * @param row zero-based row of the table
  2958.          * @return the Accessible header of the row
  2959.          */
  2960.         private Accessible getAccessibleRowHeader(int row) {
  2961.             return null;
  2962.         }
  2963.  
  2964.         /*
  2965.          * Return the Accessible representing the column header, if
  2966.          * there is one (may be null)
  2967.          *
  2968.          * @param column zero-based column of the table
  2969.          * @return the Accessible header of the column
  2970.          */
  2971.         private Accessible getAccessibleColumnHeader(int column) {
  2972.             JTableHeader header = JTable.this.getTableHeader();
  2973.             AccessibleContext ac = header.getAccessibleContext();
  2974.             if (ac != null) {
  2975.                 return ac.getAccessibleChild(column);
  2976.             } else {
  2977.                 return null;
  2978.             }
  2979.         }
  2980.  
  2981.  
  2982.         /**
  2983.          * The class used to obtain the AccessibleRole for a cell.
  2984.          */
  2985.         protected class AccessibleJTableCell extends AccessibleContext
  2986.             implements Accessible, AccessibleComponent {
  2987.  
  2988.             private JTable parent;
  2989.             private int row;
  2990.             private int column;
  2991.             private int index;
  2992.  
  2993.             /**
  2994.              *  Constructs an AccessiblJTableHeaaderEntry
  2995.              */
  2996.             public AccessibleJTableCell(JTable t, int r, int c, int i) {
  2997.                 parent = t;
  2998.                 row = r;
  2999.                 column = c;
  3000.                 index = i;
  3001.                 this.setAccessibleParent(parent);
  3002.             }
  3003.  
  3004.             /**
  3005.              * Get the AccessibleContext associated with this
  3006.              *
  3007.              * @return the AccessibleContext of this JComponent
  3008.              */
  3009.             public AccessibleContext getAccessibleContext() {
  3010.                 return this;
  3011.             }
  3012.  
  3013.             private AccessibleContext getCurrentAccessibleContext() {
  3014.                 TableColumn aColumn = getColumnModel().getColumn(column);
  3015.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  3016.                 if (renderer == null) {
  3017.                     Class columnClass = getColumnClass(column);
  3018.                     renderer = getDefaultRenderer(columnClass);
  3019.                 }
  3020.                 Component component = renderer.getTableCellRendererComponent(
  3021.                                   JTable.this, null, false, false,
  3022.                                   row, column);
  3023.                 if (component instanceof Accessible) {
  3024.                     return ((Accessible) component).getAccessibleContext();
  3025.                 } else {
  3026.                     return null;
  3027.                 }
  3028.             }
  3029.  
  3030.             private Component getCurrentComponent() {
  3031.                 TableColumn aColumn = getColumnModel().getColumn(column);
  3032.                 TableCellRenderer renderer = aColumn.getCellRenderer();
  3033.                 if (renderer == null) {
  3034.                     Class columnClass = getColumnClass(column);
  3035.                     renderer = getDefaultRenderer(columnClass);
  3036.                 }
  3037.                 return renderer.getTableCellRendererComponent(
  3038.                                   JTable.this, null, false, false,
  3039.                                   row, column);
  3040.             }
  3041.  
  3042.         // AccessibleContext methods
  3043.  
  3044.             /**
  3045.              * Get the accessible name of this object.
  3046.              *
  3047.              * @return the localized name of the object; null if this
  3048.              * object does not have a name
  3049.              */
  3050.             public String getAccessibleName() {
  3051.                 AccessibleContext ac = getCurrentAccessibleContext();
  3052.                 if (ac != null) {
  3053.                     String name = ac.getAccessibleName();
  3054.                     if ((name != null) && (name != "")) {
  3055.                         return ac.getAccessibleName();
  3056.                     }
  3057.                 }
  3058.                 if ((accessibleName != null) && (accessibleName != "")) {
  3059.                     return accessibleName;
  3060.                 } else {
  3061.                     return parent.getValueAt(row, column).toString();
  3062.                 }
  3063.             }
  3064.  
  3065.             /**
  3066.              * Set the localized accessible name of this object.
  3067.              *
  3068.              * @param s the new localized name of the object.
  3069.              */
  3070.             public void setAccessibleName(String s) {
  3071.                 AccessibleContext ac = getCurrentAccessibleContext();
  3072.                 if (ac != null) {
  3073.                     ac.setAccessibleName(s);
  3074.                 } else {
  3075.                     super.setAccessibleName(s);
  3076.                 }
  3077.             }
  3078.  
  3079.             //
  3080.             // *** should check toolip text for desc. (needs MouseEvent)
  3081.             //
  3082.             /**
  3083.              * Get the accessible description of this object.
  3084.              *
  3085.              * @return the localized description of the object; null if
  3086.              * this object does not have a description
  3087.              */
  3088.             public String getAccessibleDescription() {
  3089.                 AccessibleContext ac = getCurrentAccessibleContext();
  3090.                 if (ac != null) {
  3091.                     return ac.getAccessibleDescription();
  3092.                 } else {
  3093.                     return super.getAccessibleDescription();
  3094.                 }
  3095.             }
  3096.  
  3097.             /**
  3098.              * Set the accessible description of this object.
  3099.              *
  3100.              * @param s the new localized description of the object
  3101.              */
  3102.             public void setAccessibleDescription(String s) {
  3103.                 AccessibleContext ac = getCurrentAccessibleContext();
  3104.                 if (ac != null) {
  3105.                     ac.setAccessibleDescription(s);
  3106.                 } else {
  3107.                     super.setAccessibleDescription(s);
  3108.                 }
  3109.             }
  3110.  
  3111.             /**
  3112.              * Get the role of this object.
  3113.              *
  3114.              * @return an instance of AccessibleRole describing the role of the object
  3115.              * @see AccessibleRole
  3116.              */
  3117.             public AccessibleRole getAccessibleRole() {
  3118.                 AccessibleContext ac = getCurrentAccessibleContext();
  3119.                 if (ac != null) {
  3120.                     return ac.getAccessibleRole();
  3121.                 } else {
  3122.                     return AccessibleRole.UNKNOWN;
  3123.                 }
  3124.             }
  3125.  
  3126.             /**
  3127.              * Get the state set of this object.
  3128.              *
  3129.              * @return an instance of AccessibleStateSet containing the
  3130.              * current state set of the object
  3131.              * @see AccessibleState
  3132.              */
  3133.             public AccessibleStateSet getAccessibleStateSet() {
  3134.                 AccessibleContext ac = getCurrentAccessibleContext();
  3135.                 if (ac != null) {
  3136.                     return ac.getAccessibleStateSet();
  3137.                 } else {
  3138.                     return new AccessibleStateSet();  // must be non null?
  3139.                 }
  3140.             }
  3141.  
  3142.             /**
  3143.              * Get the Accessible parent of this object.
  3144.              *
  3145.              * @return the Accessible parent of this object; null if this
  3146.              * object does not have an Accessible parent
  3147.              */
  3148.             public Accessible getAccessibleParent() {
  3149.                 return parent;
  3150.             }
  3151.  
  3152.             /**
  3153.              * Get the index of this object in its accessible parent.
  3154.              *
  3155.              * @return the index of this object in its parent; -1 if this
  3156.              * object does not have an accessible parent.
  3157.              * @see #getAccessibleParent
  3158.              */
  3159.             public int getAccessibleIndexInParent() {
  3160.                 return index;
  3161.             }
  3162.  
  3163.             /**
  3164.              * Returns the number of accessible children in the object.
  3165.              *
  3166.              * @return the number of accessible children in the object.
  3167.              */
  3168.             public int getAccessibleChildrenCount() {
  3169.                 AccessibleContext ac = getCurrentAccessibleContext();
  3170.                 if (ac != null) {
  3171.                     return ac.getAccessibleChildrenCount();
  3172.                 } else {
  3173.                     return 0;
  3174.                 }
  3175.             }
  3176.  
  3177.             /**
  3178.              * Return the specified Accessible child of the object.
  3179.              *
  3180.              * @param i zero-based index of child
  3181.              * @return the Accessible child of the object
  3182.              */
  3183.             public Accessible getAccessibleChild(int i) {
  3184.                 AccessibleContext ac = getCurrentAccessibleContext();
  3185.                 if (ac != null) {
  3186.                     Accessible accessibleChild = ac.getAccessibleChild(i);
  3187.                     ac.setAccessibleParent(this);
  3188.                     return accessibleChild;
  3189.                 } else {
  3190.                     return null;
  3191.                 }
  3192.             }
  3193.  
  3194.             /**
  3195.              * Gets the locale of the component. If the component does not have a
  3196.              * locale, then the locale of its parent is returned.
  3197.              *
  3198.              * @return This component's locale. If this component does not have a locale, the locale of its parent is returned.
  3199.              * @exception IllegalComponentStateException
  3200.              * If the Component does not have its own locale and has not yet been added to a containment hierarchy such that the locale can be
  3201.              * determined from the containing parent.
  3202.              * @see setLocale
  3203.              */
  3204.             public Locale getLocale() {
  3205.                 AccessibleContext ac = getCurrentAccessibleContext();
  3206.                 if (ac != null) {
  3207.                     return ac.getLocale();
  3208.                 } else {
  3209.                     return null;
  3210.                 }
  3211.             }
  3212.  
  3213.             /**
  3214.              * Add a PropertyChangeListener to the listener list.
  3215.              * The listener is registered for all properties.
  3216.              *
  3217.              * @param listener  The PropertyChangeListener to be added
  3218.              */
  3219.             public void addPropertyChangeListener(PropertyChangeListener l) {
  3220.                 AccessibleContext ac = getCurrentAccessibleContext();
  3221.                 if (ac != null) {
  3222.                     ac.addPropertyChangeListener(l);
  3223.                 } else {
  3224.                     super.addPropertyChangeListener(l);
  3225.                 }
  3226.             }
  3227.  
  3228.             /**
  3229.              * Remove a PropertyChangeListener from the listener list.
  3230.              * This removes a PropertyChangeListener that was registered
  3231.              * for all properties.
  3232.              *
  3233.              * @param listener  The PropertyChangeListener to be removed
  3234.              */
  3235.             public void removePropertyChangeListener(PropertyChangeListener l) {
  3236.                 AccessibleContext ac = getCurrentAccessibleContext();
  3237.                 if (ac != null) {
  3238.                     ac.removePropertyChangeListener(l);
  3239.                 } else {
  3240.                     super.removePropertyChangeListener(l);
  3241.                 }
  3242.             }
  3243.  
  3244.             /**
  3245.              * Get the AccessibleAction associated with this object if one
  3246.              * exists.  Otherwise return null.
  3247.              *
  3248.              * @return the AccessibleAction, or null
  3249.              */
  3250.             public AccessibleAction getAccessibleAction() {
  3251.                 return getCurrentAccessibleContext().getAccessibleAction();
  3252.             }
  3253.  
  3254.             /**
  3255.              * Get the AccessibleComponent associated with this object if one
  3256.              * exists.  Otherwise return null.
  3257.              *
  3258.              * @return the AccessibleComponent, or null
  3259.              */
  3260.             public AccessibleComponent getAccessibleComponent() {
  3261.                 return this; // to override getBounds()
  3262.             }
  3263.  
  3264.             /**
  3265.              * Get the AccessibleSelection associated with this object if one
  3266.              * exists.  Otherwise return null.
  3267.              *
  3268.              * @return the AccessibleSelection, or null
  3269.              */
  3270.             public AccessibleSelection getAccessibleSelection() {
  3271.                 return getCurrentAccessibleContext().getAccessibleSelection();
  3272.             }
  3273.  
  3274.             /**
  3275.              * Get the AccessibleText associated with this object if one
  3276.              * exists.  Otherwise return null.
  3277.              *
  3278.              * @return the AccessibleText, or null
  3279.              */
  3280.             public AccessibleText getAccessibleText() {
  3281.                 return getCurrentAccessibleContext().getAccessibleText();
  3282.             }
  3283.  
  3284.             /**
  3285.              * Get the AccessibleValue associated with this object if one
  3286.              * exists.  Otherwise return null.
  3287.              *
  3288.              * @return the AccessibleValue, or null
  3289.              */
  3290.             public AccessibleValue getAccessibleValue() {
  3291.                 return getCurrentAccessibleContext().getAccessibleValue();
  3292.             }
  3293.  
  3294.  
  3295.         // AccessibleComponent methods
  3296.  
  3297.             /**
  3298.              * Get the background color of this object.
  3299.              *
  3300.              * @return the background color, if supported, of the object;
  3301.              * otherwise, null
  3302.              */
  3303.             public Color getBackground() {
  3304.                 AccessibleContext ac = getCurrentAccessibleContext();
  3305.                 if (ac instanceof AccessibleComponent) {
  3306.                     return ((AccessibleComponent) ac).getBackground();
  3307.                 } else {
  3308.                     Component c = getCurrentComponent();
  3309.                     if (c != null) {
  3310.                         return c.getBackground();
  3311.                     } else {
  3312.                         return null;
  3313.                     }
  3314.                 }
  3315.             }
  3316.  
  3317.             /**
  3318.              * Set the background color of this object.
  3319.              *
  3320.              * @param c the new Color for the background
  3321.              */
  3322.             public void setBackground(Color c) {
  3323.                 AccessibleContext ac = getCurrentAccessibleContext();
  3324.                 if (ac instanceof AccessibleComponent) {
  3325.                     ((AccessibleComponent) ac).setBackground(c);
  3326.                 } else {
  3327.                     Component cp = getCurrentComponent();
  3328.                     if (cp != null) {
  3329.                         cp.setBackground(c);
  3330.                     }
  3331.                 }
  3332.             }
  3333.  
  3334.             /**
  3335.              * Get the foreground color of this object.
  3336.              *
  3337.              * @return the foreground color, if supported, of the object;
  3338.              * otherwise, null
  3339.              */
  3340.             public Color getForeground() {
  3341.                 AccessibleContext ac = getCurrentAccessibleContext();
  3342.                 if (ac instanceof AccessibleComponent) {
  3343.                     return ((AccessibleComponent) ac).getForeground();
  3344.                 } else {
  3345.                     Component c = getCurrentComponent();
  3346.                     if (c != null) {
  3347.                         return c.getForeground();
  3348.                     } else {
  3349.                         return null;
  3350.                     }
  3351.                 }
  3352.             }
  3353.  
  3354.             /**
  3355.              * Set the foreground color of this object.
  3356.              *
  3357.              * @param c the new Color for the foreground
  3358.              */
  3359.             public void setForeground(Color c) {
  3360.                 AccessibleContext ac = getCurrentAccessibleContext();
  3361.                 if (ac instanceof AccessibleComponent) {
  3362.                     ((AccessibleComponent) ac).setForeground(c);
  3363.                 } else {
  3364.                     Component cp = getCurrentComponent();
  3365.                     if (cp != null) {
  3366.                         cp.setForeground(c);
  3367.                     }
  3368.                 }
  3369.             }
  3370.  
  3371.             /**
  3372.              * Get the Cursor of this object.
  3373.              *
  3374.              * @return the Cursor, if supported, of the object; otherwise, null
  3375.              */
  3376.             public Cursor getCursor() {
  3377.                 AccessibleContext ac = getCurrentAccessibleContext();
  3378.                 if (ac instanceof AccessibleComponent) {
  3379.                     return ((AccessibleComponent) ac).getCursor();
  3380.                 } else {
  3381.                     Component c = getCurrentComponent();
  3382.                     if (c != null) {
  3383.                         return c.getCursor();
  3384.                     } else {
  3385.                         Accessible ap = getAccessibleParent();
  3386.                         if (ap instanceof AccessibleComponent) {
  3387.                             return ((AccessibleComponent) ap).getCursor();
  3388.                         } else {
  3389.                             return null;
  3390.                         }
  3391.                     }
  3392.                 }
  3393.             }
  3394.  
  3395.             /**
  3396.              * Set the Cursor of this object.
  3397.              *
  3398.              * @param c the new Cursor for the object
  3399.              */
  3400.             public void setCursor(Cursor c) {
  3401.                 AccessibleContext ac = getCurrentAccessibleContext();
  3402.                 if (ac instanceof AccessibleComponent) {
  3403.                     ((AccessibleComponent) ac).setCursor(c);
  3404.                 } else {
  3405.                     Component cp = getCurrentComponent();
  3406.                     if (cp != null) {
  3407.                         cp.setCursor(c);
  3408.                     }
  3409.                 }
  3410.             }
  3411.  
  3412.             /**
  3413.              * Get the Font of this object.
  3414.              *
  3415.              * @return the Font,if supported, for the object; otherwise, null
  3416.              */
  3417.             public Font getFont() {
  3418.                 AccessibleContext ac = getCurrentAccessibleContext();
  3419.                 if (ac instanceof AccessibleComponent) {
  3420.                     return ((AccessibleComponent) ac).getFont();
  3421.                 } else {
  3422.                     Component c = getCurrentComponent();
  3423.                     if (c != null) {
  3424.                         return c.getFont();
  3425.                     } else {
  3426.                         return null;
  3427.                     }
  3428.                 }
  3429.             }
  3430.  
  3431.             /**
  3432.              * Set the Font of this object.
  3433.              *
  3434.              * @param f the new Font for the object
  3435.              */
  3436.             public void setFont(Font f) {
  3437.                 AccessibleContext ac = getCurrentAccessibleContext();
  3438.                 if (ac instanceof AccessibleComponent) {
  3439.                     ((AccessibleComponent) ac).setFont(f);
  3440.                 } else {
  3441.                     Component c = getCurrentComponent();
  3442.                     if (c != null) {
  3443.                         c.setFont(f);
  3444.                     }
  3445.                 }
  3446.             }
  3447.  
  3448.             /**
  3449.              * Get the FontMetrics of this object.
  3450.              *
  3451.              * @param f the Font
  3452.              * @return the FontMetrics, if supported, the object; otherwise, null
  3453.              * @see getFont
  3454.              */
  3455.             public FontMetrics getFontMetrics(Font f) {
  3456.                 AccessibleContext ac = getCurrentAccessibleContext();
  3457.                 if (ac instanceof AccessibleComponent) {
  3458.                     return ((AccessibleComponent) ac).getFontMetrics(f);
  3459.                 } else {
  3460.                     Component c = getCurrentComponent();
  3461.                     if (c != null) {
  3462.                         return c.getFontMetrics(f);
  3463.                     } else {
  3464.                         return null;
  3465.                     }
  3466.                 }
  3467.             }
  3468.  
  3469.             /**
  3470.              * Determine if the object is enabled.
  3471.              *
  3472.              * @return true if object is enabled; otherwise, false
  3473.              */
  3474.             public boolean isEnabled() {
  3475.                 AccessibleContext ac = getCurrentAccessibleContext();
  3476.                 if (ac instanceof AccessibleComponent) {
  3477.                     return ((AccessibleComponent) ac).isEnabled();
  3478.                 } else {
  3479.                     Component c = getCurrentComponent();
  3480.                     if (c != null) {
  3481.                         return c.isEnabled();
  3482.                     } else {
  3483.                         return false;
  3484.                     }
  3485.                 }
  3486.             }
  3487.  
  3488.             /**
  3489.              * Set the enabled state of the object.
  3490.              *
  3491.              * @param b if true, enables this object; otherwise, disables it
  3492.              */
  3493.             public void setEnabled(boolean b) {
  3494.                 AccessibleContext ac = getCurrentAccessibleContext();
  3495.                 if (ac instanceof AccessibleComponent) {
  3496.                     ((AccessibleComponent) ac).setEnabled(b);
  3497.                 } else {
  3498.                     Component c = getCurrentComponent();
  3499.                     if (c != null) {
  3500.                         c.setEnabled(b);
  3501.                     }
  3502.                 }
  3503.             }
  3504.  
  3505.             /**
  3506.              * Determine if the object is visible.  Note: this means that the
  3507.              * object intends to be visible; however, it may not in fact be
  3508.              * showing on the screen because one of the objects that this object
  3509.              * is contained by is not visible.  To determine if an object is
  3510.              * showing on the screen, use isShowing().
  3511.              *
  3512.              * @return true if object is visible; otherwise, false
  3513.              */
  3514.             public boolean isVisible() {
  3515.                 AccessibleContext ac = getCurrentAccessibleContext();
  3516.                 if (ac instanceof AccessibleComponent) {
  3517.                     return ((AccessibleComponent) ac).isVisible();
  3518.                 } else {
  3519.                     Component c = getCurrentComponent();
  3520.                     if (c != null) {
  3521.                         return c.isVisible();
  3522.                     } else {
  3523.                         return false;
  3524.                     }
  3525.                 }
  3526.             }
  3527.  
  3528.             /**
  3529.              * Set the visible state of the object.
  3530.              *
  3531.              * @param b if true, shows this object; otherwise, hides it
  3532.              */
  3533.             public void setVisible(boolean b) {
  3534.                 AccessibleContext ac = getCurrentAccessibleContext();
  3535.                 if (ac instanceof AccessibleComponent) {
  3536.                     ((AccessibleComponent) ac).setVisible(b);
  3537.                 } else {
  3538.                     Component c = getCurrentComponent();
  3539.                     if (c != null) {
  3540.                         c.setVisible(b);
  3541.                     }
  3542.                 }
  3543.             }
  3544.  
  3545.             /**
  3546.              * Determine if the object is showing.  This is determined by checking
  3547.              * the visibility of the object and ancestors of the object.  Note: this
  3548.              * will return true even if the object is obscured by another (for example,
  3549.              * it happens to be underneath a menu that was pulled down).
  3550.              *
  3551.              * @return true if object is showing; otherwise, false
  3552.              */
  3553.             public boolean isShowing() {
  3554.                 AccessibleContext ac = getCurrentAccessibleContext();
  3555.                 if (ac instanceof AccessibleComponent) {
  3556.                     return ((AccessibleComponent) ac).isShowing();
  3557.                 } else {
  3558.                     Component c = getCurrentComponent();
  3559.                     if (c != null) {
  3560.                         return c.isShowing();
  3561.                     } else {
  3562.                         return false;
  3563.                     }
  3564.                 }
  3565.             }
  3566.  
  3567.             /**
  3568.              * Checks whether the specified point is within this object's bounds,
  3569.              * where the point's x and y coordinates are defined to be relative to the
  3570.              * coordinate system of the object.
  3571.              *
  3572.              * @param p the Point relative to the coordinate system of the object
  3573.              * @return true if object contains Point; otherwise false
  3574.              */
  3575.             public boolean contains(Point p) {
  3576.                 AccessibleContext ac = getCurrentAccessibleContext();
  3577.                 if (ac instanceof AccessibleComponent) {
  3578.                     Rectangle r = ((AccessibleComponent) ac).getBounds();
  3579.                     return r.contains(p);
  3580.                 } else {
  3581.                     Component c = getCurrentComponent();
  3582.                     if (c != null) {
  3583.                         Rectangle r = c.getBounds();
  3584.                         return r.contains(p);
  3585.                     } else {
  3586.                         return getBounds().contains(p);
  3587.                     }
  3588.                 }
  3589.             }
  3590.  
  3591.             /**
  3592.              * Returns the location of the object on the screen.
  3593.              *
  3594.              * @return location of object on screen -- can be null if this object
  3595.              * is not on the screen
  3596.              */
  3597.             public Point getLocationOnScreen() {
  3598.                 if (parent != null) {
  3599.                     Point parentLocation = parent.getLocationOnScreen();
  3600.                     Point componentLocation = getLocation();
  3601.                     componentLocation.translate(parentLocation.x, parentLocation.y);
  3602.                     return componentLocation;
  3603.                 } else {
  3604.                     return null;
  3605.                 }
  3606.             }
  3607.  
  3608.             /**
  3609.              * Gets the location of the object relative to the parent in the form
  3610.              * of a point specifying the object's top-left corner in the screen's
  3611.              * coordinate space.
  3612.              *
  3613.              * @return An instance of Point representing the top-left corner of the
  3614.              * objects's bounds in the coordinate space of the screen; null if
  3615.              * this object or its parent are not on the screen
  3616.              */
  3617.             public Point getLocation() {
  3618.                 if (parent != null) {
  3619.                     Rectangle r = parent.getCellRect(row, column, false);
  3620.                     if (r != null) {
  3621.                         return r.getLocation();
  3622.                     }
  3623.                 }
  3624.                 return null;
  3625.             }
  3626.  
  3627.             /**
  3628.              * Sets the location of the object relative to the parent.
  3629.              */
  3630.             public void setLocation(Point p) {
  3631. //              if ((parent != null)  && (parent.contains(p))) {
  3632. //                  ensureIndexIsVisible(indexInParent);
  3633. //              }
  3634.             }
  3635.  
  3636.             public Rectangle getBounds() {
  3637.                 if (parent != null) {
  3638.                     return parent.getCellRect(row, column, false);
  3639.                 } else {
  3640.                     return null;
  3641.                 }
  3642.             }
  3643.  
  3644.             public void setBounds(Rectangle r) {
  3645.                 AccessibleContext ac = getCurrentAccessibleContext();
  3646.                 if (ac instanceof AccessibleComponent) {
  3647.                     ((AccessibleComponent) ac).setBounds(r);
  3648.                 } else {
  3649.                     Component c = getCurrentComponent();
  3650.                     if (c != null) {
  3651.                         c.setBounds(r);
  3652.                     }
  3653.                 }
  3654.             }
  3655.  
  3656.             public Dimension getSize() {
  3657.                 if (parent != null) {
  3658.                     Rectangle r = parent.getCellRect(row, column, false);
  3659.                     if (r != null) {
  3660.                         return r.getSize();
  3661.                     }
  3662.                 }
  3663.                 return null;
  3664.             }
  3665.  
  3666.             public void setSize (Dimension d) {
  3667.                 AccessibleContext ac = getCurrentAccessibleContext();
  3668.                 if (ac instanceof AccessibleComponent) {
  3669.                     ((AccessibleComponent) ac).setSize(d);
  3670.                 } else {
  3671.                     Component c = getCurrentComponent();
  3672.                     if (c != null) {
  3673.                         c.setSize(d);
  3674.                     }
  3675.                 }
  3676.             }
  3677.  
  3678.             public Accessible getAccessibleAt(Point p) {
  3679.                 AccessibleContext ac = getCurrentAccessibleContext();
  3680.                 if (ac instanceof AccessibleComponent) {
  3681.                     return ((AccessibleComponent) ac).getAccessibleAt(p);
  3682.                 } else {
  3683.                     return null;
  3684.                 }
  3685.             }
  3686.  
  3687.             public boolean isFocusTraversable() {
  3688.                 AccessibleContext ac = getCurrentAccessibleContext();
  3689.                 if (ac instanceof AccessibleComponent) {
  3690.                     return ((AccessibleComponent) ac).isFocusTraversable();
  3691.                 } else {
  3692.                     Component c = getCurrentComponent();
  3693.                     if (c != null) {
  3694.                         return c.isFocusTraversable();
  3695.                     } else {
  3696.                         return false;
  3697.                     }
  3698.                 }
  3699.             }
  3700.  
  3701.             public void requestFocus() {
  3702.                 AccessibleContext ac = getCurrentAccessibleContext();
  3703.                 if (ac instanceof AccessibleComponent) {
  3704.                     ((AccessibleComponent) ac).requestFocus();
  3705.                 } else {
  3706.                     Component c = getCurrentComponent();
  3707.                     if (c != null) {
  3708.                         c.requestFocus();
  3709.                     }
  3710.                 }
  3711.             }
  3712.  
  3713.             public void addFocusListener(FocusListener l) {
  3714.                 AccessibleContext ac = getCurrentAccessibleContext();
  3715.                 if (ac instanceof AccessibleComponent) {
  3716.                     ((AccessibleComponent) ac).addFocusListener(l);
  3717.                 } else {
  3718.                     Component c = getCurrentComponent();
  3719.                     if (c != null) {
  3720.                         c.addFocusListener(l);
  3721.                     }
  3722.                 }
  3723.             }
  3724.  
  3725.             public void removeFocusListener(FocusListener l) {
  3726.                 AccessibleContext ac = getCurrentAccessibleContext();
  3727.                 if (ac instanceof AccessibleComponent) {
  3728.                     ((AccessibleComponent) ac).removeFocusListener(l);
  3729.                 } else {
  3730.                     Component c = getCurrentComponent();
  3731.                     if (c != null) {
  3732.                         c.removeFocusListener(l);
  3733.                     }
  3734.                 }
  3735.             }
  3736.  
  3737.         } // inner class AccessibleJTableCell
  3738.  
  3739.     }  // inner class AccessibleJTable
  3740.  
  3741. }  // End of Class JTable
  3742.